Place drawings on sheets

When adding a drawing to a sheet, place to the right of the last drawing
if it fits on the sheet - otherwise start a new row below all existing
drawings.

This means that new drawings are no longer just piled up on top of each
other at the top-left, but it does mean that new rows of drawings are
added below the title box when the sheet is full.
This commit is contained in:
Bruno Postle
2025-03-21 23:37:30 +00:00
parent 25b7003d2d
commit 775106d0a0
+48 -12
View File
@@ -32,6 +32,7 @@ from mathutils import Vector
import re
VIEW_TITLE_OFFSET_Y = 5
DRAWING_PADDING = 10
DEFAULT_POSITION = Vector((30, 30))
SVG = "{http://www.w3.org/2000/svg}"
XLINK = "{http://www.w3.org/1999/xlink}"
@@ -113,13 +114,15 @@ class SheetBuilder:
view_width = self.convert_to_mm(view_root.attrib.get("width"))
view_height = self.convert_to_mm(view_root.attrib.get("height"))
x, y = self.next_drawing_location(layout_root, view_width)
# add background
if os.path.isfile(underlay_path):
background = ET.SubElement(view, "image")
background.attrib["data-type"] = "background"
background.attrib["xlink:href"] = os.path.relpath(underlay_path, layout_dir)
background.attrib["x"] = str(DEFAULT_POSITION.x)
background.attrib["y"] = str(DEFAULT_POSITION.y)
background.attrib["x"] = str(x)
background.attrib["y"] = str(y)
background.attrib["width"] = str(view_width)
background.attrib["height"] = str(view_height)
@@ -128,16 +131,49 @@ class SheetBuilder:
foreground = ET.SubElement(view, "image")
foreground.attrib["data-type"] = "foreground"
foreground.attrib["xlink:href"] = os.path.relpath(drawing_path, layout_dir)
foreground.attrib["x"] = str(DEFAULT_POSITION.x)
foreground.attrib["y"] = str(DEFAULT_POSITION.y)
foreground.attrib["x"] = str(x)
foreground.attrib["y"] = str(y)
foreground.attrib["width"] = str(view_width)
foreground.attrib["height"] = str(view_height)
self.add_view_title(
DEFAULT_POSITION.x, view_height + DEFAULT_POSITION.y + VIEW_TITLE_OFFSET_Y, view, layout_dir
)
self.add_view_title(x, view_height + y + VIEW_TITLE_OFFSET_Y, view, layout_dir)
layout_tree.write(layout_path)
def next_drawing_location(self, layout_root: ET.Element, next_width: float) -> list:
titleblocks = layout_root.findall(f'{SVG}g[@data-type="titleblock"]')
drawings = layout_root.findall(f'{SVG}g[@data-type="drawing"]')
# how wide is the title block frame
try:
titleblock_width = self.convert_to_mm(titleblocks[0][0].attrib.get("width"))
except (IndexError, AttributeError):
titleblock_width = 840.0
# where does the last drawing finish
try:
last = drawings[-1][0]
last_width = self.convert_to_mm(last.attrib.get("width"))
last_x = self.convert_to_mm(last.attrib.get("x"))
last_y = self.convert_to_mm(last.attrib.get("y"))
except (IndexError, AttributeError):
return [DEFAULT_POSITION.x, DEFAULT_POSITION.y]
# check if the new drawing fits in the current row
if last_x + last_width + DRAWING_PADDING + next_width + DEFAULT_POSITION.x < titleblock_width:
return [last_x + last_width + DRAWING_PADDING, last_y]
# start a new row, find the y
for drawing in drawings:
for image in drawing:
try:
image_y = self.convert_to_mm(image.attrib.get("y"))
image_height = self.convert_to_mm(image.attrib.get("height"))
except AttributeError:
return [DEFAULT_POSITION.x, DEFAULT_POSITION.y]
if image_y + image_height + DRAWING_PADDING > last_y:
last_y = image_y + image_height + DRAWING_PADDING
return [DEFAULT_POSITION.x, last_y]
def update_sheet_drawing_sizes(self, sheet: ifcopenshell.entity_instance) -> None:
ET.register_namespace("", "http://www.w3.org/2000/svg")
@@ -221,6 +257,8 @@ class SheetBuilder:
view_width = self.convert_to_mm(view_root.attrib.get("width"))
view_height = self.convert_to_mm(view_root.attrib.get("height"))
x, y = self.next_drawing_location(layout_root, view_width)
view = ET.SubElement(layout_root, "g")
view.attrib["data-id"] = str(reference.id())
view.attrib["data-type"] = document.Scope.lower()
@@ -229,14 +267,12 @@ class SheetBuilder:
foreground = ET.SubElement(view, "image")
foreground.attrib["data-type"] = "content"
foreground.attrib["xlink:href"] = os.path.relpath(view_path, layout_dir)
foreground.attrib["x"] = str(DEFAULT_POSITION.x)
foreground.attrib["y"] = str(DEFAULT_POSITION.y)
foreground.attrib["x"] = str(x)
foreground.attrib["y"] = str(y)
foreground.attrib["width"] = str(view_width)
foreground.attrib["height"] = str(view_height)
self.add_view_title(
DEFAULT_POSITION.x, view_height + DEFAULT_POSITION.y + VIEW_TITLE_OFFSET_Y, view, layout_dir
)
self.add_view_title(x, view_height + y + VIEW_TITLE_OFFSET_Y, view, layout_dir)
layout_tree.write(layout_path)
def add_view_title(self, x: float, y: float, parent: ET.Element, layout_dir: str) -> None: