mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-18 03:19:53 +00:00
Closes #7877:Add scale to reference view-title from SVG class
When a reference drawing is added to a sheet, the sheet
builder now reads the `scale-X` CSS class from the reference
SVG content and uses it to populate the {{Scale}} field in
the view-title. The scale denominator is resolved to a
human-readable string (e.g. "scale-4" → '3"=1\'-0"') using
the Blender scene unit system to pick imperial vs. metric.
Generated with the assistance of an AI coding tool.
This commit is contained in:
@@ -486,11 +486,29 @@ class SheetBuilder:
|
||||
data.update({"Sheet" + k: v for k, v in sheet.get_info().items()})
|
||||
if not data["Name"]:
|
||||
data["Name"] = document.Name or "Unnamed"
|
||||
if view.attrib.get("data-type") == "reference":
|
||||
human_scale = self.get_scale_from_svg(os.path.join(self.layout_dir, path))
|
||||
if human_scale:
|
||||
data["Scale"] = human_scale
|
||||
view.append(self.parse_embedded_svg(view_title, data))
|
||||
|
||||
for image in images:
|
||||
view.remove(image)
|
||||
|
||||
def get_scale_from_svg(self, svg_path: str) -> str:
|
||||
try:
|
||||
tree = ET.parse(svg_path)
|
||||
root = tree.getroot()
|
||||
for g in root.iter(f"{SVG}g"):
|
||||
for cls in g.attrib.get("class", "").split():
|
||||
if cls.startswith("scale-"):
|
||||
denominator = cls[6:]
|
||||
if denominator.isdigit():
|
||||
return tool.Drawing.get_human_scale_from_scale_denominator(denominator)
|
||||
except Exception:
|
||||
pass
|
||||
return ""
|
||||
|
||||
def get_href(self, element: ET.Element) -> str:
|
||||
return urllib.parse.unquote(element.attrib[f"{XLINK}href"]).replace("\\", "/")
|
||||
|
||||
|
||||
@@ -2227,6 +2227,63 @@ class Drawing(bonsai.core.tool.Drawing):
|
||||
pset = ifcopenshell.util.element.get_pset(drawing, "EPset_Drawing") or {}
|
||||
return "NTS" if pset.get("IsNTS", False) else pset.get("HumanScale", "NTS")
|
||||
|
||||
@classmethod
|
||||
def get_human_scale_from_scale_denominator(cls, denominator: str) -> str:
|
||||
"""Return the human-readable scale string for a scale CSS class denominator.
|
||||
|
||||
E.g. denominator '4' returns '3"=1\'-0"' (imperial) or '' if not found.
|
||||
"""
|
||||
IMPERIAL_SCALES = {
|
||||
"1": "1'=1'-0\"",
|
||||
"2": '6"=1\'-0"',
|
||||
"4": '3"=1\'-0"',
|
||||
"8": '1-1/2"=1\'-0"',
|
||||
"12": '1"=1\'-0"',
|
||||
"16": '3/4"=1\'-0"',
|
||||
"24": '1/2"=1\'-0"',
|
||||
"32": '3/8"=1\'-0"',
|
||||
"48": '1/4"=1\'-0"',
|
||||
"64": '3/16"=1\'-0"',
|
||||
"96": '1/8"=1\'-0"',
|
||||
"128": '3/32"=1\'-0"',
|
||||
"192": '1/16"=1\'-0"',
|
||||
"384": '1/32"=1\'-0"',
|
||||
"768": '1/64"=1\'-0"',
|
||||
"1536": '1/128"=1\'-0"',
|
||||
"120": "1\"=10'",
|
||||
"240": "1\"=20'",
|
||||
"360": "1\"=30'",
|
||||
"480": "1\"=40'",
|
||||
"600": "1\"=50'",
|
||||
"720": "1\"=60'",
|
||||
"840": "1\"=70'",
|
||||
"960": "1\"=80'",
|
||||
"1080": "1\"=90'",
|
||||
"1200": "1\"=100'",
|
||||
"1800": "1\"=150'",
|
||||
"2400": "1\"=200'",
|
||||
"3600": "1\"=300'",
|
||||
"4800": "1\"=400'",
|
||||
"6000": "1\"=500'",
|
||||
}
|
||||
METRIC_SCALES = {
|
||||
"5000": "1:5000",
|
||||
"2000": "1:2000",
|
||||
"1000": "1:1000",
|
||||
"500": "1:500",
|
||||
"200": "1:200",
|
||||
"100": "1:100",
|
||||
"50": "1:50",
|
||||
"20": "1:20",
|
||||
"10": "1:10",
|
||||
"5": "1:5",
|
||||
"2": "1:2",
|
||||
"1": "1:1",
|
||||
}
|
||||
import bpy
|
||||
is_imperial = bpy.context.scene.unit_settings.system == "IMPERIAL"
|
||||
return (IMPERIAL_SCALES if is_imperial else METRIC_SCALES).get(denominator, "")
|
||||
|
||||
@classmethod
|
||||
def get_drawing_metadata(cls, drawing: ifcopenshell.entity_instance) -> list[str]:
|
||||
pset_data = ifcopenshell.util.element.get_pset(drawing, "EPset_Drawing")
|
||||
|
||||
Reference in New Issue
Block a user