See #2516. WARNING: breaking changes! Restructure drawing system to use relative paths based on IfcDocumentReference Locations.
|
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 5.6 KiB |
|
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 67 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 4.4 KiB |
@@ -24,6 +24,7 @@ import zipfile
|
||||
import tempfile
|
||||
import ifcopenshell
|
||||
import blenderbim.bim.handler
|
||||
import blenderbim.tool as tool
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
@@ -371,7 +372,7 @@ class IfcStore:
|
||||
def unlink_element(element=None, obj=None):
|
||||
if element is None:
|
||||
try:
|
||||
element = IfcStore.get_file().by_id(obj.BIMObjectProperties.ifc_definition_id)
|
||||
element = tool.Ifc.get_entity(obj)
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
@@ -179,6 +179,7 @@ class CreateDrawing(bpy.types.Operator):
|
||||
|
||||
self.camera = context.scene.camera
|
||||
self.camera_element = tool.Ifc.get_entity(self.camera)
|
||||
self.camera_document = tool.Drawing.get_drawing_document(self.camera_element)
|
||||
self.file = IfcStore.get_file()
|
||||
|
||||
with profile("Drawing generation process"):
|
||||
@@ -198,14 +199,8 @@ class CreateDrawing(bpy.types.Operator):
|
||||
self.svg_writer.camera_projection = tuple(
|
||||
self.camera.matrix_world.to_quaternion() @ Vector((0, 0, -1))
|
||||
)
|
||||
pset = ifcopenshell.util.element.get_psets(self.camera_element)["EPset_Drawing"]
|
||||
related_paths = {
|
||||
"Stylesheet": pset.get("Stylesheet"),
|
||||
"Markers": pset.get("Markers"),
|
||||
"Symbols": pset.get("Symbols"),
|
||||
"Patterns": pset.get("Patterns"),
|
||||
}
|
||||
self.svg_writer.define_related_paths(**related_paths)
|
||||
|
||||
self.svg_writer.setup_drawing_resource_paths(self.camera_element)
|
||||
|
||||
with profile("Generate underlay"):
|
||||
underlay_svg = self.generate_underlay(context)
|
||||
@@ -237,7 +232,7 @@ class CreateDrawing(bpy.types.Operator):
|
||||
|
||||
def combine_svgs(self, context, underlay, linework, annotation):
|
||||
# Hacky :)
|
||||
svg_path = os.path.join(context.scene.BIMProperties.data_dir, "diagrams", self.drawing_name + ".svg")
|
||||
svg_path = self.get_svg_path()
|
||||
with open(svg_path, "w") as outfile:
|
||||
self.svg_writer.create_blank_svg(svg_path).define_boilerplate()
|
||||
boilerplate = self.svg_writer.svg.tostring()
|
||||
@@ -282,7 +277,7 @@ class CreateDrawing(bpy.types.Operator):
|
||||
def generate_underlay(self, context):
|
||||
if not self.cprops.has_underlay:
|
||||
return
|
||||
svg_path = os.path.join(context.scene.BIMProperties.data_dir, "cache", self.drawing_name + "-underlay.svg")
|
||||
svg_path = self.get_svg_path(cache_type="underlay")
|
||||
context.scene.render.filepath = svg_path[0:-4] + ".png"
|
||||
drawing_style = context.scene.DocProperties.drawing_styles[self.cprops.active_drawing_style_index]
|
||||
|
||||
@@ -322,7 +317,7 @@ class CreateDrawing(bpy.types.Operator):
|
||||
def generate_linework(self, context):
|
||||
if not self.cprops.has_linework:
|
||||
return
|
||||
svg_path = os.path.join(context.scene.BIMProperties.data_dir, "cache", self.drawing_name + "-linework.svg")
|
||||
svg_path = self.get_svg_path(cache_type="linework")
|
||||
if os.path.isfile(svg_path) and self.props.should_use_linework_cache:
|
||||
return svg_path
|
||||
|
||||
@@ -605,7 +600,7 @@ class CreateDrawing(bpy.types.Operator):
|
||||
def generate_annotation(self, context):
|
||||
if not self.cprops.has_annotation:
|
||||
return
|
||||
svg_path = os.path.join(context.scene.BIMProperties.data_dir, "cache", self.drawing_name + "-annotation.svg")
|
||||
svg_path = self.get_svg_path(cache_type="annotation")
|
||||
if os.path.isfile(svg_path) and self.props.should_use_annotation_cache:
|
||||
return svg_path
|
||||
|
||||
@@ -662,6 +657,17 @@ class CreateDrawing(bpy.types.Operator):
|
||||
return element.LayerSetName
|
||||
return "mat-" + str(element.id())
|
||||
|
||||
def get_svg_path(self, cache_type=None):
|
||||
drawing_path = tool.Drawing.get_document_uri(self.camera_document)
|
||||
drawings_dir = os.path.dirname(drawing_path)
|
||||
|
||||
if cache_type:
|
||||
drawings_dir = os.path.join(drawings_dir, "cache")
|
||||
os.makedirs(drawings_dir, exist_ok=True)
|
||||
return os.path.join(drawings_dir, f"{self.drawing_name}-{cache_type}.svg")
|
||||
os.makedirs(drawings_dir, exist_ok=True)
|
||||
return drawing_path
|
||||
|
||||
|
||||
class AddAnnotation(bpy.types.Operator, Operator):
|
||||
bl_idname = "bim.add_annotation"
|
||||
@@ -711,7 +717,7 @@ class OpenSheet(bpy.types.Operator, Operator):
|
||||
core.open_sheet(tool.Drawing, sheet=sheet)
|
||||
|
||||
|
||||
class AddDrawingToSheet(bpy.types.Operator):
|
||||
class AddDrawingToSheet(bpy.types.Operator, Operator):
|
||||
bl_idname = "bim.add_drawing_to_sheet"
|
||||
bl_label = "Add Drawing To Sheet"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
@@ -721,11 +727,13 @@ class AddDrawingToSheet(bpy.types.Operator):
|
||||
props = context.scene.DocProperties
|
||||
return props.drawings and props.sheets and context.scene.BIMProperties.data_dir
|
||||
|
||||
def execute(self, context):
|
||||
def _execute(self, context):
|
||||
props = context.scene.DocProperties
|
||||
active_drawing = props.drawings[props.active_drawing_index]
|
||||
active_sheet = props.sheets[props.active_sheet_index]
|
||||
drawing = tool.Ifc.get().by_id(active_drawing.ifc_definition_id)
|
||||
drawing_uri = tool.Drawing.get_document_uri(tool.Drawing.get_drawing_document(drawing))
|
||||
|
||||
sheet = tool.Ifc.get().by_id(active_sheet.ifc_definition_id)
|
||||
if not sheet.is_a("IfcDocumentInformation"):
|
||||
return {"FINISHED"}
|
||||
@@ -737,13 +745,7 @@ class AddDrawingToSheet(bpy.types.Operator):
|
||||
|
||||
has_drawing = False
|
||||
for reference in references:
|
||||
if tool.Ifc.get_schema() == "IFC2X3":
|
||||
element = [r for r in tool.Ifc.by_type("IfcRelAssociatesDocument") if r.RelatingDocument == reference][
|
||||
0
|
||||
].RelatedObjects[0]
|
||||
else:
|
||||
element = reference.DocumentRefForObjects[0].RelatedObjects[0]
|
||||
if element == drawing:
|
||||
if reference.Location == drawing_uri:
|
||||
has_drawing = True
|
||||
break
|
||||
|
||||
@@ -756,7 +758,6 @@ class AddDrawingToSheet(bpy.types.Operator):
|
||||
else:
|
||||
attributes = {"Identification": str(len(sheet.HasDocumentReferences or []))}
|
||||
tool.Ifc.run("document.edit_reference", reference=reference, attributes=attributes)
|
||||
tool.Ifc.run("document.assign_document", product=drawing, document=reference)
|
||||
sheet_builder = sheeter.SheetBuilder()
|
||||
sheet_builder.data_dir = context.scene.BIMProperties.data_dir
|
||||
sheet_builder.add_drawing(reference, drawing, sheet)
|
||||
@@ -810,15 +811,19 @@ class CreateSheets(bpy.types.Operator):
|
||||
name = os.path.splitext(os.path.basename(tool.Drawing.get_document_uri(sheet)))[0]
|
||||
sheet_builder = sheeter.SheetBuilder()
|
||||
sheet_builder.data_dir = scene.BIMProperties.data_dir
|
||||
sheet_builder.build(sheet)
|
||||
|
||||
# These variables will be made available to the evaluated commands
|
||||
svg = sheet_builder.build(sheet)
|
||||
basename = os.path.basename(svg)
|
||||
path = os.path.dirname(svg)
|
||||
pdf = os.path.splitext(svg)[0] + ".pdf"
|
||||
eps = os.path.splitext(svg)[0] + ".eps"
|
||||
dxf = os.path.splitext(svg)[0] + ".dxf"
|
||||
|
||||
svg2pdf_command = context.preferences.addons["blenderbim"].preferences.svg2pdf_command
|
||||
svg2dxf_command = context.preferences.addons["blenderbim"].preferences.svg2dxf_command
|
||||
|
||||
if svg2pdf_command:
|
||||
path = os.path.join(scene.BIMProperties.data_dir, "build", name)
|
||||
svg = os.path.join(path, name + ".svg")
|
||||
pdf = os.path.join(path, name + ".pdf")
|
||||
# With great power comes great responsibility. Example:
|
||||
# [['inkscape', svg, '-o', pdf]]
|
||||
commands = eval(svg2pdf_command)
|
||||
@@ -826,11 +831,6 @@ class CreateSheets(bpy.types.Operator):
|
||||
subprocess.run(command)
|
||||
|
||||
if svg2dxf_command:
|
||||
path = os.path.join(scene.BIMProperties.data_dir, "build", name)
|
||||
svg = os.path.join(path, name + ".svg")
|
||||
eps = os.path.join(path, name + ".eps")
|
||||
dxf = os.path.join(path, name + ".dxf")
|
||||
base = os.path.join(path, name)
|
||||
# With great power comes great responsibility. Example:
|
||||
# [['inkscape', svg, '-o', eps], ['pstoedit', '-dt', '-f', 'dxf:-polyaslines -mm', eps, dxf, '-psarg', '-dNOSAFER']]
|
||||
commands = eval(svg2dxf_command)
|
||||
@@ -840,10 +840,7 @@ class CreateSheets(bpy.types.Operator):
|
||||
if svg2pdf_command:
|
||||
open_with_user_command(context.preferences.addons["blenderbim"].preferences.pdf_command, pdf)
|
||||
else:
|
||||
open_with_user_command(
|
||||
context.preferences.addons["blenderbim"].preferences.svg_command,
|
||||
os.path.join(scene.BIMProperties.data_dir, "build", name, name + ".svg"),
|
||||
)
|
||||
open_with_user_command(context.preferences.addons["blenderbim"].preferences.svg_command, svg)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
@@ -894,19 +891,19 @@ class OpenView(bpy.types.Operator):
|
||||
return self.execute(context)
|
||||
|
||||
def execute(self, context):
|
||||
if not self.open_all:
|
||||
view_list = [self.view]
|
||||
if self.open_all:
|
||||
drawings = [tool.Ifc.get().by_id(d.ifc_definition_id) for d in context.scene.DocProperties.drawings]
|
||||
else:
|
||||
view_list = [d.name for d in context.scene.DocProperties.drawings]
|
||||
drawings = [tool.Ifc.get().by_id(context.scene.DocProperties.drawings.get(self.view).ifc_definition_id)]
|
||||
|
||||
data_dir = Path(context.scene.BIMProperties.data_dir)
|
||||
diagrams = []
|
||||
drawing_uris = []
|
||||
drawings_not_found = []
|
||||
for view_name in view_list.copy():
|
||||
path = data_dir / "diagrams" / (view_name + ".svg")
|
||||
if not path.is_file():
|
||||
drawings_not_found.append(view_name)
|
||||
diagrams.append(path)
|
||||
|
||||
for drawing in drawings:
|
||||
drawing_uri = tool.Drawing.get_document_uri(tool.Drawing.get_drawing_document(drawing))
|
||||
drawing_uris.append(drawing_uri)
|
||||
if not os.path.exists(drawing_uri):
|
||||
drawings_not_found.append(drawing.Name)
|
||||
|
||||
if drawings_not_found:
|
||||
msg = "Some drawings .svg files were not found, need to print them first: \n{}.".format(
|
||||
@@ -915,11 +912,8 @@ class OpenView(bpy.types.Operator):
|
||||
self.report({"ERROR"}, msg)
|
||||
return {"CANCELLED"}
|
||||
|
||||
for diagram_path in diagrams:
|
||||
open_with_user_command(
|
||||
context.preferences.addons["blenderbim"].preferences.svg_command,
|
||||
str(diagram_path),
|
||||
)
|
||||
for drawing_uri in drawing_uris:
|
||||
open_with_user_command(context.preferences.addons["blenderbim"].preferences.svg_command, drawing_uri)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
@@ -1143,12 +1137,15 @@ class AddSchedule(bpy.types.Operator, Operator):
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
filepath: bpy.props.StringProperty(subtype="FILE_PATH")
|
||||
filter_glob: bpy.props.StringProperty(default="*.ods;*.xls;*.xlsx", options={"HIDDEN"})
|
||||
use_relative_path: bpy.props.BoolProperty(name="Use Relative Path", default=False)
|
||||
use_relative_path: bpy.props.BoolProperty(name="Use Relative Path", default=True)
|
||||
|
||||
def _execute(self, context):
|
||||
filepath = self.filepath
|
||||
if self.use_relative_path:
|
||||
filepath = os.path.relpath(filepath, bpy.path.abspath("//"))
|
||||
ifc_path = tool.Ifc.get_path()
|
||||
if os.path.isfile(ifc_path):
|
||||
ifc_path = os.path.dirname(ifc_path)
|
||||
filepath = os.path.relpath(filepath, ifc_path)
|
||||
core.add_schedule(
|
||||
tool.Ifc,
|
||||
tool.Drawing,
|
||||
@@ -1216,7 +1213,7 @@ class AddScheduleToSheet(bpy.types.Operator):
|
||||
|
||||
has_schedule = False
|
||||
for reference in references:
|
||||
if reference.Location == tool.Drawing.get_schedule_location(schedule):
|
||||
if reference.Location == tool.Drawing.get_path_with_ext(tool.Drawing.get_document_uri(schedule), "svg"):
|
||||
has_schedule = True
|
||||
break
|
||||
|
||||
|
||||
@@ -354,6 +354,13 @@ class DocProperties(PropertyGroup):
|
||||
decorations_colour: FloatVectorProperty(
|
||||
name="Decorations Colour", subtype="COLOR", default=(1, 1, 1, 1), min=0.0, max=1.0, size=4
|
||||
)
|
||||
docs_dir: StringProperty(default=os.path.join(".", "docs") + os.path.sep, name="Default Docs Directory")
|
||||
sheets_dir: StringProperty(default=os.path.join(".", "sheets") + os.path.sep, name="Default Sheets Directory")
|
||||
drawings_dir: StringProperty(default=os.path.join(".", "drawings") + os.path.sep, name="Default Drawings Directory")
|
||||
stylesheet_path: StringProperty(default=os.path.join(".", "drawings", "assets", "default.css"), name="Default Stylesheet")
|
||||
markers_path: StringProperty(default=os.path.join(".", "drawings", "assets", "markers.svg"), name="Default Markers")
|
||||
symbols_path: StringProperty(default=os.path.join(".", "drawings", "assets", "symbols.svg"), name="Default Symbols")
|
||||
patterns_path: StringProperty(default=os.path.join(".", "drawings", "assets", "patterns.svg"), name="Default Patterns")
|
||||
|
||||
|
||||
class BIMCameraProperties(PropertyGroup):
|
||||
|
||||
@@ -17,14 +17,15 @@
|
||||
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import os
|
||||
import bpy
|
||||
import uuid
|
||||
import shutil
|
||||
import ntpath
|
||||
import pystache
|
||||
import urllib.parse
|
||||
import xml.etree.ElementTree as ET
|
||||
import blenderbim.tool as tool
|
||||
import ifcopenshell.util.geolocation
|
||||
from shutil import copy
|
||||
from xml.dom import minidom
|
||||
|
||||
|
||||
@@ -40,15 +41,14 @@ class SheetBuilder:
|
||||
root.attrib["id"] = "root"
|
||||
root.attrib["version"] = "1.1"
|
||||
|
||||
view_root = ET.parse(
|
||||
os.path.join(self.data_dir, "templates", "titleblocks", titleblock_name + ".svg")
|
||||
).getroot()
|
||||
titleblock_path = os.path.join(self.data_dir, "templates", "titleblocks", titleblock_name + ".svg")
|
||||
view_root = ET.parse(titleblock_path).getroot()
|
||||
view_width = self.convert_to_mm(view_root.attrib.get("width"))
|
||||
view_height = self.convert_to_mm(view_root.attrib.get("height"))
|
||||
view = ET.SubElement(root, "g")
|
||||
view.attrib["data-type"] = "titleblock"
|
||||
titleblock = ET.SubElement(view, "image")
|
||||
titleblock.attrib["xlink:href"] = f"../templates/titleblocks/{titleblock_name}.svg"
|
||||
titleblock.attrib["xlink:href"] = f"./titleblocks/{titleblock_name}.svg"
|
||||
titleblock.attrib["x"] = "0"
|
||||
titleblock.attrib["y"] = "0"
|
||||
titleblock.attrib["width"] = str(view_width)
|
||||
@@ -58,17 +58,24 @@ class SheetBuilder:
|
||||
root.attrib["height"] = "{}mm".format(view_height)
|
||||
root.attrib["viewBox"] = "0 0 {} {}".format(view_width, view_height)
|
||||
|
||||
sheet_dir = os.path.dirname(sheet_path)
|
||||
os.makedirs(sheet_dir, exist_ok=True)
|
||||
os.makedirs(os.path.join(sheet_dir, "titleblocks"), exist_ok=True)
|
||||
sheet_titleblock_path = os.path.join(sheet_dir, "titleblocks", titleblock_name + ".svg")
|
||||
if not os.path.exists(sheet_titleblock_path):
|
||||
shutil.copy(titleblock_path, sheet_titleblock_path)
|
||||
with open(sheet_path, "w") as f:
|
||||
f.write(minidom.parseString(ET.tostring(root)).toprettyxml(indent=" "))
|
||||
|
||||
def add_drawing(self, reference, drawing, sheet):
|
||||
filename = drawing.Name
|
||||
sheet_name = os.path.splitext(os.path.basename(tool.Drawing.get_document_uri(sheet)))[0]
|
||||
sheet_dir = os.path.join(self.data_dir, "sheets")
|
||||
drawing_dir = os.path.join(self.data_dir, "diagrams")
|
||||
sheet_path = os.path.join(sheet_dir, sheet_name + ".svg")
|
||||
drawing_path = os.path.join(drawing_dir, filename + ".svg")
|
||||
underlay_path = os.path.join(drawing_dir, filename + "-underlay.png")
|
||||
sheet_path = tool.Drawing.get_document_uri(sheet)
|
||||
sheet_name = os.path.splitext(os.path.basename(sheet_path))[0]
|
||||
sheet_dir = os.path.dirname(sheet_path)
|
||||
|
||||
drawing_path = tool.Drawing.get_document_uri(tool.Drawing.get_drawing_reference(drawing))
|
||||
drawing_path = tool.Ifc.resolve_uri(drawing_path)
|
||||
underlay_path = os.path.splitext(drawing_path)[0] + "-underlay.png"
|
||||
|
||||
if not os.path.isfile(sheet_path):
|
||||
raise FileNotFoundError
|
||||
@@ -110,7 +117,7 @@ class SheetBuilder:
|
||||
foreground.attrib["width"] = str(view_width)
|
||||
foreground.attrib["height"] = str(view_height)
|
||||
|
||||
self.add_view_title(30, view_height + 35, view)
|
||||
self.add_view_title(30, view_height + 35, view, sheet_dir)
|
||||
sheet_tree.write(sheet_path)
|
||||
|
||||
def remove_drawing(self, reference, sheet):
|
||||
@@ -128,11 +135,12 @@ class SheetBuilder:
|
||||
sheet_tree.write(sheet_path)
|
||||
|
||||
def add_schedule(self, reference, schedule, sheet):
|
||||
view_path = tool.Drawing.get_document_uri(schedule)
|
||||
view_path = tool.Drawing.get_path_with_ext(tool.Drawing.get_document_uri(schedule), "svg")
|
||||
if not os.path.exists(view_path):
|
||||
tool.Drawing.create_svg_schedule(schedule)
|
||||
schedule_name = os.path.splitext(os.path.basename(view_path))[0]
|
||||
sheet_path = tool.Drawing.get_document_uri(sheet)
|
||||
sheet_dir = os.path.dirname(sheet_path)
|
||||
|
||||
ET.register_namespace("", "http://www.w3.org/2000/svg")
|
||||
ET.register_namespace("xlink", "http://www.w3.org/1999/xlink")
|
||||
@@ -152,31 +160,40 @@ class SheetBuilder:
|
||||
|
||||
foreground = ET.SubElement(view, "image")
|
||||
foreground.attrib["data-type"] = "table"
|
||||
foreground.attrib["xlink:href"] = "../schedules/{}.svg".format(schedule_name)
|
||||
foreground.attrib["xlink:href"] = os.path.relpath(view_path, sheet_dir)
|
||||
foreground.attrib["x"] = "30"
|
||||
foreground.attrib["y"] = "30"
|
||||
foreground.attrib["width"] = str(view_width)
|
||||
foreground.attrib["height"] = str(view_height)
|
||||
|
||||
self.add_view_title(30, view_height + 35, view)
|
||||
self.add_view_title(30, view_height + 35, view, sheet_dir)
|
||||
sheet_tree.write(sheet_path)
|
||||
|
||||
def add_view_title(self, x, y, parent):
|
||||
title_tree = ET.parse(os.path.join(self.data_dir, "templates", "view-title.svg"))
|
||||
def add_view_title(self, x, y, parent, sheet_dir):
|
||||
title_path = os.path.join(sheet_dir, "assets", "view-title.svg")
|
||||
os.makedirs(os.path.dirname(title_path), exist_ok=True)
|
||||
if not os.path.exists(title_path):
|
||||
ootb_title = os.path.join(bpy.context.scene.BIMProperties.data_dir, "assets", "view-title.svg")
|
||||
shutil.copy(ootb_title, title_path)
|
||||
|
||||
title_tree = ET.parse(title_path)
|
||||
title_root = title_tree.getroot()
|
||||
title = ET.SubElement(parent, "image")
|
||||
title.attrib["data-type"] = "view-title"
|
||||
title.attrib["xlink:href"] = "../templates/view-title.svg"
|
||||
title.attrib["xlink:href"] = os.path.relpath(title_path, sheet_dir)
|
||||
title.attrib["x"] = str(x)
|
||||
title.attrib["y"] = str(y)
|
||||
title.attrib["width"] = str(self.convert_to_mm(title_root.attrib.get("width")))
|
||||
title.attrib["height"] = str(self.convert_to_mm(title_root.attrib.get("height")))
|
||||
|
||||
def build(self, sheet):
|
||||
sheet_name = os.path.splitext(os.path.basename(tool.Drawing.get_document_uri(sheet)))[0]
|
||||
os.makedirs(os.path.join(self.data_dir, "build", sheet_name), exist_ok=True)
|
||||
sheet_path = tool.Drawing.get_document_uri(sheet)
|
||||
sheet_name = os.path.splitext(os.path.basename(sheet_path))[0]
|
||||
self.sheet_dir = os.path.dirname(sheet_path)
|
||||
|
||||
sheet_path = os.path.join(self.data_dir, "sheets", f"{sheet_name}.svg")
|
||||
docs_dir = tool.Ifc.resolve_uri(os.path.join(bpy.context.scene.DocProperties.docs_dir, sheet_name))
|
||||
|
||||
os.makedirs(docs_dir, exist_ok=True)
|
||||
|
||||
ET.register_namespace("", "http://www.w3.org/2000/svg")
|
||||
ET.register_namespace("xlink", "http://www.w3.org/1999/xlink")
|
||||
@@ -191,9 +208,13 @@ class SheetBuilder:
|
||||
self.build_drawings(root, sheet)
|
||||
self.build_schedules(root)
|
||||
|
||||
with open(os.path.join(self.data_dir, "build", sheet_name, f"{sheet_name}.svg"), "wb") as output:
|
||||
output_filename = os.path.join(docs_dir, f"{sheet_name}.svg")
|
||||
|
||||
with open(output_filename, "wb") as output:
|
||||
tree.write(output)
|
||||
|
||||
return output_filename
|
||||
|
||||
def build_titleblock(self, root, sheet):
|
||||
titleblock = root.findall('{http://www.w3.org/2000/svg}g[@data-type="titleblock"]')[0]
|
||||
image = titleblock.findall("{http://www.w3.org/2000/svg}image")[0]
|
||||
@@ -233,7 +254,7 @@ class SheetBuilder:
|
||||
|
||||
if background is not None:
|
||||
background_path = os.path.join(self.data_dir, "sheets", self.get_href(background))
|
||||
copy(background_path, os.path.join(self.data_dir, "build", sheet_name))
|
||||
shutil.copy(background_path, os.path.join(self.data_dir, "build", sheet_name))
|
||||
|
||||
if view_title is not None:
|
||||
foreground_path = self.get_href(foreground)
|
||||
@@ -298,7 +319,7 @@ class SheetBuilder:
|
||||
self.defs.append(clip_path)
|
||||
|
||||
svg_path = self.get_href(image)
|
||||
with open(os.path.join(self.data_dir, "sheets", svg_path), "r") as template:
|
||||
with open(os.path.join(self.sheet_dir, svg_path), "r") as template:
|
||||
embedded = ET.fromstring(pystache.render(template.read(), data))
|
||||
# viewBox should not be nested
|
||||
embedded.attrib["viewBox"] = ""
|
||||
|
||||
@@ -21,6 +21,7 @@ import re
|
||||
import bpy
|
||||
import math
|
||||
import bmesh
|
||||
import shutil
|
||||
import pystache
|
||||
import mathutils
|
||||
import xml.etree.ElementTree as ET
|
||||
@@ -65,10 +66,9 @@ class SvgWriter:
|
||||
self.scale = 1 / 100 # 1:100
|
||||
self.camera_width = None
|
||||
self.camera_height = None
|
||||
self.related_paths = None
|
||||
self.resource_paths = {}
|
||||
|
||||
def create_blank_svg(self, output_path):
|
||||
self.define_related_paths() # making sure all paths are defined
|
||||
self.calculate_scale()
|
||||
self.svg = svgwrite.Drawing(
|
||||
output_path,
|
||||
@@ -94,26 +94,19 @@ class SvgWriter:
|
||||
)
|
||||
return self
|
||||
|
||||
def define_related_paths(self, **related_paths):
|
||||
if not self.related_paths:
|
||||
self.related_paths = {}
|
||||
|
||||
if not related_paths:
|
||||
related_paths = {
|
||||
"Stylesheet": os.path.join(self.data_dir, "styles", f"default.css"),
|
||||
"Markers": os.path.join(self.data_dir, "templates", "markers.svg"),
|
||||
"Symbols": os.path.join(self.data_dir, "templates", "symbols.svg"),
|
||||
"Patterns": os.path.join(self.data_dir, "templates", "patterns.svg"),
|
||||
}
|
||||
for path_name in list(related_paths.keys()):
|
||||
if path_name in self.related_paths:
|
||||
del related_paths[path_name]
|
||||
|
||||
for path_name in related_paths:
|
||||
uri = related_paths[path_name]
|
||||
custom_path = tool.Ifc.resolve_uri(uri)
|
||||
if custom_path:
|
||||
self.related_paths[path_name] = custom_path
|
||||
def setup_drawing_resource_paths(self, element):
|
||||
pset = ifcopenshell.util.element.get_pset(element, "EPset_Drawing")
|
||||
for resource in ("Stylesheet", "Markers", "Symbols", "Patterns"):
|
||||
resource_path = pset.get(resource)
|
||||
if not resource_path:
|
||||
continue
|
||||
os.makedirs(os.path.dirname(resource_path), exist_ok=True)
|
||||
if not os.path.exists(resource_path):
|
||||
resource_basename = os.path.basename(resource_path)
|
||||
ootb_resource = os.path.join(bpy.context.scene.BIMProperties.data_dir, "assets", resource_basename)
|
||||
if os.path.exists(ootb_resource):
|
||||
shutil.copy(ootb_resource, resource_path)
|
||||
self.resource_paths[resource] = tool.Ifc.resolve_uri(resource_path)
|
||||
|
||||
def define_boilerplate(self):
|
||||
self.add_stylesheet()
|
||||
@@ -132,28 +125,36 @@ class SvgWriter:
|
||||
self.height = self.raw_height * self.svg_scale
|
||||
|
||||
def add_stylesheet(self):
|
||||
with open(self.related_paths["Stylesheet"], "r") as stylesheet:
|
||||
if not self.resource_paths["Stylesheet"] or not os.path.exists(self.resource_paths["Stylesheet"]):
|
||||
return
|
||||
with open(self.resource_paths["Stylesheet"], "r") as stylesheet:
|
||||
self.svg.defs.add(self.svg.style(stylesheet.read()))
|
||||
|
||||
def add_markers(self):
|
||||
tree = ET.parse(self.related_paths["Markers"])
|
||||
if not self.resource_paths["Markers"] or not os.path.exists(self.resource_paths["Markers"]):
|
||||
return
|
||||
tree = ET.parse(self.resource_paths["Markers"])
|
||||
root = tree.getroot()
|
||||
for child in root:
|
||||
self.svg.defs.add(External(child))
|
||||
|
||||
def add_symbols(self):
|
||||
tree = ET.parse(self.related_paths["Symbols"])
|
||||
if not self.resource_paths["Symbols"] or not os.path.exists(self.resource_paths["Symbols"]):
|
||||
return
|
||||
tree = ET.parse(self.resource_paths["Symbols"])
|
||||
root = tree.getroot()
|
||||
for child in root:
|
||||
self.svg.defs.add(External(child))
|
||||
|
||||
def find_xml_symbol_by_id(self, id):
|
||||
tree = ET.parse(self.related_paths["Symbols"])
|
||||
tree = ET.parse(self.resource_paths["Symbols"])
|
||||
xml_symbol = tree.find(f'.//*[@id="{id}"]')
|
||||
return External(xml_symbol) if xml_symbol else None
|
||||
|
||||
def add_patterns(self):
|
||||
tree = ET.parse(self.related_paths["Patterns"])
|
||||
if not self.resource_paths["Patterns"] or not os.path.exists(self.resource_paths["Patterns"]):
|
||||
return
|
||||
tree = ET.parse(self.resource_paths["Patterns"])
|
||||
root = tree.getroot()
|
||||
for child in root:
|
||||
self.svg.defs.add(External(child))
|
||||
|
||||
@@ -182,6 +182,21 @@ class BIM_ADDON_preferences(bpy.types.AddonPreferences):
|
||||
row.prop(context.scene.BIMProperties, "data_dir")
|
||||
row.operator("bim.select_data_dir", icon="FILE_FOLDER", text="")
|
||||
|
||||
row = self.layout.row(align=True)
|
||||
row.prop(context.scene.DocProperties, "docs_dir")
|
||||
row = self.layout.row(align=True)
|
||||
row.prop(context.scene.DocProperties, "sheets_dir")
|
||||
row = self.layout.row(align=True)
|
||||
row.prop(context.scene.DocProperties, "drawings_dir")
|
||||
row = self.layout.row(align=True)
|
||||
row.prop(context.scene.DocProperties, "stylesheet_path")
|
||||
row = self.layout.row(align=True)
|
||||
row.prop(context.scene.DocProperties, "markers_path")
|
||||
row = self.layout.row(align=True)
|
||||
row.prop(context.scene.DocProperties, "symbols_path")
|
||||
row = self.layout.row(align=True)
|
||||
row.prop(context.scene.DocProperties, "patterns_path")
|
||||
|
||||
row = layout.row()
|
||||
row.operator("bim.configure_visibility")
|
||||
|
||||
|
||||
@@ -72,6 +72,9 @@ def add_sheet(ifc, drawing, titleblock=None):
|
||||
if ifc.get_schema() == "IFC2X3":
|
||||
attributes["DocumentId"] = attributes["Identification"]
|
||||
del attributes["Identification"]
|
||||
# TODO: How does IFC2X3 store the location?
|
||||
else:
|
||||
attributes["Location"] = drawing.get_default_sheet_path(identification, "UNTITLED")
|
||||
ifc.run("document.edit_information", information=sheet, attributes=attributes)
|
||||
drawing.create_svg_sheet(sheet, titleblock)
|
||||
drawing.import_sheets()
|
||||
@@ -103,13 +106,13 @@ def disable_editing_schedules(drawing):
|
||||
def add_schedule(ifc, drawing, uri=None):
|
||||
schedule = ifc.run("document.add_information")
|
||||
reference = ifc.run("document.add_reference", information=schedule)
|
||||
name = drawing.get_path_filename(uri)
|
||||
if ifc.get_schema() == "IFC2X3":
|
||||
attributes = {"DocumentId": "X", "Name": "UNTITLED", "Scope": "SCHEDULE"}
|
||||
ifc.run("document.edit_information", information=schedule, attributes=attributes)
|
||||
ifc.run("document.edit_reference", reference=reference, attributes={"Location": uri})
|
||||
attributes = {"DocumentId": "X", "Name": name, "Scope": "SCHEDULE"}
|
||||
else:
|
||||
attributes = {"Identification": "X", "Name": "UNTITLED", "Scope": "SCHEDULE", "Location": uri}
|
||||
ifc.run("document.edit_information", information=schedule, attributes=attributes)
|
||||
attributes = {"Identification": "X", "Name": name, "Scope": "SCHEDULE"}
|
||||
ifc.run("document.edit_information", information=schedule, attributes=attributes)
|
||||
ifc.run("document.edit_reference", reference=reference, attributes={"Location": uri})
|
||||
drawing.import_schedules()
|
||||
|
||||
|
||||
@@ -119,7 +122,7 @@ def remove_schedule(ifc, drawing, schedule=None):
|
||||
|
||||
|
||||
def open_schedule(drawing, schedule=None):
|
||||
drawing.open_spreadsheet(drawing.get_schedule_location(schedule))
|
||||
drawing.open_spreadsheet(drawing.get_document_uri(schedule))
|
||||
|
||||
|
||||
def update_schedule_name(ifc, drawing, schedule=None, name=None):
|
||||
@@ -164,8 +167,22 @@ def add_drawing(ifc, collector, drawing, target_view=None, location_hint=None):
|
||||
"HasLinework": True,
|
||||
"HasAnnotation": True,
|
||||
"GlobalReferencing": True,
|
||||
"Stylesheet": drawing.get_default_drawing_resource_path("Stylesheet"),
|
||||
"Markers": drawing.get_default_drawing_resource_path("Markers"),
|
||||
"Symbols": drawing.get_default_drawing_resource_path("Symbols"),
|
||||
"Patterns": drawing.get_default_drawing_resource_path("Patterns"),
|
||||
},
|
||||
)
|
||||
information = ifc.run("document.add_information")
|
||||
uri = drawing.get_default_drawing_path(drawing_name)
|
||||
reference = ifc.run("document.add_reference", information=information)
|
||||
if ifc.get_schema() == "IFC2X3":
|
||||
attributes = {"DocumentId": "X", "Name": drawing_name, "Scope": "DRAWING"}
|
||||
else:
|
||||
attributes = {"Identification": "X", "Name": drawing_name, "Scope": "DRAWING"}
|
||||
ifc.run("document.edit_information", information=information, attributes=attributes)
|
||||
ifc.run("document.edit_reference", reference=reference, attributes={"Location": uri})
|
||||
ifc.run("document.assign_document", product=element, document=reference)
|
||||
drawing.import_drawings()
|
||||
|
||||
|
||||
@@ -204,6 +221,7 @@ def remove_drawing(ifc, drawing_tool, drawing=None):
|
||||
if reference_obj:
|
||||
drawing_tool.delete_object(reference_obj)
|
||||
ifc.run("root.remove_product", product=reference)
|
||||
ifc.run("document.remove_information", information=drawing_tool.get_drawing_document(drawing))
|
||||
ifc.run("root.remove_product", product=drawing)
|
||||
drawing_tool.import_drawings()
|
||||
|
||||
@@ -243,7 +261,7 @@ def add_annotation(ifc, collector, drawing_tool, drawing=None, object_type=None)
|
||||
|
||||
def build_schedule(drawing, schedule=None):
|
||||
drawing.create_svg_schedule(schedule)
|
||||
drawing.open_svg(drawing.get_document_uri(schedule))
|
||||
drawing.open_svg(drawing.get_path_with_ext(drawing.get_document_uri(schedule), "svg"))
|
||||
|
||||
|
||||
def sync_references(ifc, collector, drawing_tool, drawing=None):
|
||||
|
||||
@@ -255,15 +255,19 @@ class Drawing:
|
||||
def get_annotation_context(cls, target_view): pass
|
||||
def get_assigned_product(cls, element): pass
|
||||
def get_body_context(cls): pass
|
||||
def get_default_drawing_path(cls, name): pass
|
||||
def get_default_drawing_resource_path(cls, resource): pass
|
||||
def get_default_sheet_path(cls, identification, name): pass
|
||||
def get_document_uri(cls, document): pass
|
||||
def get_drawing_collection(cls, drawing): pass
|
||||
def get_drawing_document(cls, drawing): pass
|
||||
def get_drawing_group(cls, drawing): pass
|
||||
def get_path_filename(cls, uri): pass
|
||||
def get_drawing_references(cls, drawing): pass
|
||||
def get_drawing_target_view(cls, drawing): pass
|
||||
def get_group_elements(cls, group): pass
|
||||
def get_ifc_representation_class(cls, object_type): pass
|
||||
def get_name(cls, element): pass
|
||||
def get_schedule_location(cls, schedule): pass
|
||||
def get_text_literal(cls, obj): pass
|
||||
def remove_literal_from_annotation(cls, obj, literal): pass
|
||||
def synchronise_ifc_and_text_attributes(cls, obj): pass
|
||||
|
||||
@@ -128,13 +128,17 @@ class Drawing(blenderbim.core.tool.Drawing):
|
||||
@classmethod
|
||||
def create_svg_schedule(cls, schedule):
|
||||
schedule_creator = scheduler.Scheduler()
|
||||
schedule_creator.schedule(cls.get_schedule_location(schedule), cls.get_document_uri(schedule))
|
||||
schedule_creator.schedule(
|
||||
cls.get_document_uri(schedule), cls.get_path_with_ext(cls.get_document_uri(schedule), "svg")
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def create_svg_sheet(cls, document, titleblock):
|
||||
sheet_builder = sheeter.SheetBuilder()
|
||||
sheet_builder.data_dir = bpy.context.scene.BIMProperties.data_dir
|
||||
sheet_builder.create(cls.get_document_uri(document), titleblock)
|
||||
uri = cls.get_document_uri(document)
|
||||
sheet_builder.create(uri, titleblock)
|
||||
return uri
|
||||
|
||||
@classmethod
|
||||
def delete_collection(cls, collection):
|
||||
@@ -252,17 +256,28 @@ class Drawing(blenderbim.core.tool.Drawing):
|
||||
|
||||
@classmethod
|
||||
def get_document_uri(cls, document):
|
||||
if hasattr(document, "Identification"):
|
||||
name = document.Identification or "X"
|
||||
else:
|
||||
name = document.DocumentId or "X"
|
||||
name += " - " + (document.Name or "Unnamed")
|
||||
if not hasattr(document, "Scope"):
|
||||
return
|
||||
if document.Scope == "DOCUMENTATION":
|
||||
return os.path.join(bpy.context.scene.BIMProperties.data_dir, "sheets", name + ".svg")
|
||||
elif document.Scope == "SCHEDULE":
|
||||
return os.path.join(bpy.context.scene.BIMProperties.data_dir, "schedules", name + ".svg")
|
||||
if getattr(document, "Location", None):
|
||||
ifc_path = tool.Ifc.get_path()
|
||||
if os.path.isfile(ifc_path):
|
||||
ifc_path = os.path.dirname(ifc_path)
|
||||
return os.path.abspath(os.path.join(ifc_path, document.Location))
|
||||
if document.is_a("IfcDocumentInformation"):
|
||||
if tool.Ifc.get_schema() == "IFC2X3":
|
||||
references = document.DocumentReferences
|
||||
else:
|
||||
references = document.HasDocumentReferences
|
||||
for reference in references:
|
||||
location = cls.get_document_uri(reference)
|
||||
if location:
|
||||
return location
|
||||
|
||||
@classmethod
|
||||
def get_path_filename(cls, path):
|
||||
return os.path.splitext(os.path.basename(path))[0]
|
||||
|
||||
@classmethod
|
||||
def get_path_with_ext(cls, path, ext):
|
||||
return os.path.splitext(path)[0] + f".{ext}"
|
||||
|
||||
@classmethod
|
||||
def get_drawing_collection(cls, drawing):
|
||||
@@ -276,6 +291,12 @@ class Drawing(blenderbim.core.tool.Drawing):
|
||||
if rel.is_a("IfcRelAssignsToGroup"):
|
||||
return rel.RelatingGroup
|
||||
|
||||
@classmethod
|
||||
def get_drawing_document(cls, drawing):
|
||||
for rel in drawing.HasAssociations:
|
||||
if rel.is_a("IfcRelAssociatesDocument"):
|
||||
return rel.RelatingDocument
|
||||
|
||||
@classmethod
|
||||
def get_drawing_references(cls, drawing):
|
||||
results = set()
|
||||
@@ -305,12 +326,6 @@ class Drawing(blenderbim.core.tool.Drawing):
|
||||
def get_name(cls, element):
|
||||
return element.Name
|
||||
|
||||
@classmethod
|
||||
def get_schedule_location(cls, schedule):
|
||||
if tool.Ifc.get_schema() == "IFC2X3":
|
||||
return schedule.DocumentReferences[0].Location
|
||||
return schedule.Location
|
||||
|
||||
@classmethod
|
||||
def generate_drawing_matrix(cls, target_view, location_hint):
|
||||
x = 0 if location_hint == 0 else bpy.context.scene.cursor.matrix[0][3]
|
||||
@@ -721,6 +736,18 @@ class Drawing(blenderbim.core.tool.Drawing):
|
||||
return location_hint + " " + target_view.split("_")[0]
|
||||
return target_view
|
||||
|
||||
@classmethod
|
||||
def get_default_sheet_path(cls, identification, name):
|
||||
return os.path.join(bpy.context.scene.DocProperties.sheets_dir, f"{identification} - {name}.svg")
|
||||
|
||||
@classmethod
|
||||
def get_default_drawing_path(cls, name):
|
||||
return os.path.join(bpy.context.scene.DocProperties.drawings_dir, f"{name}.svg")
|
||||
|
||||
@classmethod
|
||||
def get_default_drawing_resource_path(cls, resource):
|
||||
return getattr(bpy.context.scene.DocProperties, f"{resource.lower()}_path") or None
|
||||
|
||||
@classmethod
|
||||
def get_potential_reference_elements(cls, drawing):
|
||||
elements = []
|
||||
|
||||
@@ -106,7 +106,10 @@ class Ifc(blenderbim.core.tool.Ifc):
|
||||
|
||||
@classmethod
|
||||
def resolve_uri(cls, uri):
|
||||
return uri if not uri or os.path.isabs(uri) else os.path.join(os.path.dirname(cls.get_path()), uri)
|
||||
ifc_path = cls.get_path()
|
||||
if os.path.isfile(ifc_path):
|
||||
ifc_path = os.path.dirname(ifc_path)
|
||||
return uri if not uri or os.path.isabs(uri) else os.path.join(ifc_path, uri)
|
||||
|
||||
@classmethod
|
||||
def unlink(cls, element=None, obj=None):
|
||||
|
||||
@@ -87,10 +87,11 @@ class TestAddSheet:
|
||||
drawing.generate_sheet_identification().should_be_called().will_return("identification")
|
||||
drawing.ensure_unique_identification("identification").should_be_called().will_return("u_identification")
|
||||
ifc.get_schema().should_be_called().will_return("IFC4")
|
||||
drawing.get_default_sheet_path("u_identification", "UNTITLED").should_be_called().will_return("uri")
|
||||
ifc.run(
|
||||
"document.edit_information",
|
||||
information="sheet",
|
||||
attributes={"Identification": "u_identification", "Name": "UNTITLED", "Scope": "DOCUMENTATION"},
|
||||
attributes={"Identification": "u_identification", "Name": "UNTITLED", "Scope": "DOCUMENTATION", "Location": "uri"},
|
||||
).should_be_called()
|
||||
drawing.create_svg_sheet("sheet", "titleblock").should_be_called()
|
||||
drawing.import_sheets().should_be_called()
|
||||
@@ -141,18 +142,21 @@ class TestDisableEditingSchedules:
|
||||
class TestAddSchedule:
|
||||
def test_run(self, ifc, drawing):
|
||||
ifc.run("document.add_information").should_be_called().will_return("schedule")
|
||||
drawing.get_path_filename("uri").should_be_called().will_return("UNTITLED")
|
||||
ifc.run("document.add_reference", information="schedule").should_be_called().will_return("reference")
|
||||
ifc.get_schema().should_be_called().will_return("IFC4")
|
||||
ifc.run(
|
||||
"document.edit_information",
|
||||
information="schedule",
|
||||
attributes={"Identification": "X", "Name": "UNTITLED", "Scope": "SCHEDULE", "Location": "uri"},
|
||||
attributes={"Identification": "X", "Name": "UNTITLED", "Scope": "SCHEDULE"},
|
||||
).should_be_called()
|
||||
ifc.run("document.edit_reference", reference="reference", attributes={"Location": "uri"}).should_be_called()
|
||||
drawing.import_schedules().should_be_called()
|
||||
subject.add_schedule(ifc, drawing, uri="uri")
|
||||
|
||||
def test_using_a_document_id_in_ifc2x3(self, ifc, drawing):
|
||||
ifc.run("document.add_information").should_be_called().will_return("schedule")
|
||||
drawing.get_path_filename("uri").should_be_called().will_return("UNTITLED")
|
||||
ifc.run("document.add_reference", information="schedule").should_be_called().will_return("reference")
|
||||
ifc.get_schema().should_be_called().will_return("IFC2X3")
|
||||
ifc.run(
|
||||
@@ -174,7 +178,7 @@ class TestRemoveSchedule:
|
||||
|
||||
class TestOpenSchedule:
|
||||
def test_run(self, drawing):
|
||||
drawing.get_schedule_location("schedule").should_be_called().will_return("uri")
|
||||
drawing.get_document_uri("schedule").should_be_called().will_return("uri")
|
||||
drawing.open_spreadsheet("uri").should_be_called()
|
||||
subject.open_schedule(drawing, schedule="schedule")
|
||||
|
||||
@@ -225,6 +229,10 @@ class TestAddDrawing:
|
||||
ifc.run("group.assign_group", group="group", products=["element"]).should_be_called()
|
||||
collector.assign("obj").should_be_called()
|
||||
ifc.run("pset.add_pset", product="element", name="EPset_Drawing").should_be_called().will_return("pset")
|
||||
drawing.get_default_drawing_resource_path("Stylesheet").should_be_called().will_return("stylesheet.css")
|
||||
drawing.get_default_drawing_resource_path("Markers").should_be_called().will_return("markers.svg")
|
||||
drawing.get_default_drawing_resource_path("Symbols").should_be_called().will_return("symbols.svg")
|
||||
drawing.get_default_drawing_resource_path("Patterns").should_be_called().will_return("patterns.svg")
|
||||
ifc.run(
|
||||
"pset.edit_pset",
|
||||
pset="pset",
|
||||
@@ -236,8 +244,19 @@ class TestAddDrawing:
|
||||
"HasLinework": True,
|
||||
"HasAnnotation": True,
|
||||
"GlobalReferencing": True,
|
||||
"Stylesheet": "stylesheet.css",
|
||||
"Markers": "markers.svg",
|
||||
"Symbols": "symbols.svg",
|
||||
"Patterns": "patterns.svg",
|
||||
},
|
||||
).should_be_called()
|
||||
drawing.get_default_drawing_path("name").should_be_called().will_return("uri")
|
||||
ifc.run("document.add_information").should_be_called().will_return("information")
|
||||
ifc.run("document.add_reference", information="information").should_be_called().will_return("reference")
|
||||
ifc.get_schema().should_be_called().will_return("IFC4")
|
||||
ifc.run("document.edit_information", information="information", attributes={"Identification": "X", "Name": "name", "Scope": "DRAWING"}).should_be_called()
|
||||
ifc.run("document.edit_reference", reference="reference", attributes={"Location": "uri"}).should_be_called()
|
||||
ifc.run("document.assign_document", product="element", document="reference").should_be_called()
|
||||
drawing.import_drawings().should_be_called()
|
||||
subject.add_drawing(ifc, collector, drawing, target_view="target_view", location_hint="location_hint")
|
||||
|
||||
@@ -277,6 +296,8 @@ class TestRemoveDrawing:
|
||||
ifc.get_object("reference").should_be_called().will_return("reference_obj")
|
||||
drawing.delete_object("reference_obj").should_be_called()
|
||||
ifc.run("root.remove_product", product="reference").should_be_called()
|
||||
drawing.get_drawing_document("drawing").should_be_called().will_return("information")
|
||||
ifc.run("document.remove_information", information="information").should_be_called()
|
||||
ifc.run("root.remove_product", product="drawing").should_be_called()
|
||||
drawing.import_drawings().should_be_called()
|
||||
subject.remove_drawing(ifc, drawing, drawing="drawing")
|
||||
|
||||
@@ -61,9 +61,15 @@ class TestCreateCamera(NewFile):
|
||||
class TestCreateSvgSheet(NewFile):
|
||||
def test_run(self):
|
||||
ifc = ifcopenshell.file()
|
||||
document = ifc.createIfcDocumentInformation(Identification="X", Name="FOOBAR", Scope="DOCUMENTATION")
|
||||
subject.create_svg_sheet(document, "A1")
|
||||
assert os.path.isfile(os.path.join(bpy.context.scene.BIMProperties.data_dir, "sheets", "X - FOOBAR.svg"))
|
||||
document = ifc.createIfcDocumentInformation(
|
||||
Identification="X",
|
||||
Name="FOOBAR",
|
||||
Scope="DOCUMENTATION",
|
||||
Location=os.path.join(bpy.context.scene.BIMProperties.data_dir, "cache", "X - FOOBAR.svg"),
|
||||
)
|
||||
uri = subject.create_svg_sheet(document, "A1")
|
||||
assert uri.endswith(".svg")
|
||||
assert os.path.isfile(uri)
|
||||
|
||||
|
||||
class TestDeleteCollection(NewFile):
|
||||
@@ -204,11 +210,13 @@ class TestEnsureUniqueIdentification(NewFile):
|
||||
class TestExportTextLiteralAttributes(NewFile):
|
||||
def test_run(self):
|
||||
TestImportTextAttributes().test_run()
|
||||
assert subject.export_text_literal_attributes(bpy.data.objects.get("Object")) == [{
|
||||
"Literal": "Literal",
|
||||
"Path": "RIGHT",
|
||||
"BoxAlignment": "bottom-left",
|
||||
}]
|
||||
assert subject.export_text_literal_attributes(bpy.data.objects.get("Object")) == [
|
||||
{
|
||||
"Literal": "Literal",
|
||||
"Path": "RIGHT",
|
||||
"BoxAlignment": "bottom-left",
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
class TestGetAnnotationContext(NewFile):
|
||||
@@ -236,23 +244,29 @@ class TestGetBodyContext(NewFile):
|
||||
|
||||
|
||||
class TestGetDocumentUri(NewFile):
|
||||
def test_get_sheet_uri(self):
|
||||
def test_run(self):
|
||||
ifc = ifcopenshell.file()
|
||||
document = ifc.createIfcDocumentInformation(
|
||||
Identification="X", Name="FOOBAR", Scope="DOCUMENTATION", Location="Location"
|
||||
)
|
||||
assert subject.get_document_uri(document) == os.path.abspath(os.path.join(tool.Ifc.get_path(), "Location"))
|
||||
|
||||
def test_get_indirect_locations(self):
|
||||
ifc = ifcopenshell.file()
|
||||
document = ifc.createIfcDocumentInformation(Identification="X", Name="FOOBAR", Scope="DOCUMENTATION")
|
||||
result = subject.get_document_uri(document)
|
||||
assert result == os.path.join(bpy.context.scene.BIMProperties.data_dir, "sheets", "X - FOOBAR.svg")
|
||||
|
||||
def test_get_schedule_uri(self):
|
||||
ifc = ifcopenshell.file()
|
||||
document = ifc.createIfcDocumentInformation(Identification="X", Name="FOOBAR", Scope="SCHEDULE")
|
||||
result = subject.get_document_uri(document)
|
||||
assert result == os.path.join(bpy.context.scene.BIMProperties.data_dir, "schedules", "X - FOOBAR.svg")
|
||||
reference = ifc.createIfcDocumentReference(Location="Location", ReferencedDocument=document)
|
||||
assert subject.get_document_uri(document) == os.path.abspath(os.path.join(tool.Ifc.get_path(), "Location"))
|
||||
assert subject.get_document_uri(reference) == os.path.abspath(os.path.join(tool.Ifc.get_path(), "Location"))
|
||||
|
||||
def test_run_ifc2x3(self):
|
||||
ifc = ifcopenshell.file(schema="IFC2X3")
|
||||
document = ifc.createIfcDocumentInformation(DocumentId="X", Name="FOOBAR", Scope="DOCUMENTATION")
|
||||
result = subject.get_document_uri(document)
|
||||
assert result == os.path.join(bpy.context.scene.BIMProperties.data_dir, "sheets", "X - FOOBAR.svg")
|
||||
tool.Ifc.set(ifc)
|
||||
reference = ifc.createIfcDocumentReference(Location="Location")
|
||||
document = ifc.createIfcDocumentInformation(
|
||||
DocumentId="X", Name="FOOBAR", Scope="DOCUMENTATION", DocumentReferences=[reference]
|
||||
)
|
||||
assert subject.get_document_uri(document) == os.path.abspath(os.path.join(tool.Ifc.get_path(), "Location"))
|
||||
assert subject.get_document_uri(reference) == os.path.abspath(os.path.join(tool.Ifc.get_path(), "Location"))
|
||||
|
||||
|
||||
class TestGetDrawingCollection(NewFile):
|
||||
@@ -311,23 +325,6 @@ class TestGetName(NewFile):
|
||||
assert subject.get_name(ifc.createIfcWall(Name="Foobar")) == "Foobar"
|
||||
|
||||
|
||||
class TestGetScheduleLocation(NewFile):
|
||||
def test_run(self):
|
||||
ifc = ifcopenshell.file()
|
||||
ifcopenshell.api.run("root.create_entity", ifc, ifc_class="IfcProject")
|
||||
schedule = ifcopenshell.api.run("document.add_information", ifc)
|
||||
schedule.Location = "uri"
|
||||
reference = ifcopenshell.api.run("document.add_reference", ifc, information=schedule)
|
||||
subject.get_schedule_location(schedule) == "uri"
|
||||
|
||||
def test_run_ifc2x3(self):
|
||||
ifc = ifcopenshell.file(schema="IFC2X3")
|
||||
tool.Ifc.set(ifc)
|
||||
reference = ifc.createIfcDocumentReference(Location="uri")
|
||||
schedule = ifc.createIfcDocumentInformation(DocumentReferences=[reference])
|
||||
subject.get_schedule_location(schedule) == "uri"
|
||||
|
||||
|
||||
class TestGenerateDrawingMatrix(NewFile):
|
||||
def test_returning_the_origin_as_a_fallback(self):
|
||||
assert subject.generate_drawing_matrix("PLAN_VIEW", None) == mathutils.Matrix()
|
||||
|
||||