MPM Document Standard 1.3, mpmdoc build engine, templates for TN, INS, SOP, BOM, SVY, TAP, DWG, TSB, PRO, SOW and WO (Chinese editions for TN and DWG), glossary, MPM fonts and logos, and the mpm-technical-documents plugin 1.3.0. Worked examples ship in the kit zip on Drive only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NWatTMmqmGatgHjDZvWs5b
71 lines
4.1 KiB
Python
71 lines
4.1 KiB
Python
"""Shared SVG helpers for figures. Import what you need in a project's figs.py:
|
|
|
|
from mpmdoc.figkit import T, svg_open, markers, INK, GOLD, KICK, ...
|
|
|
|
Conventions (MPM_Document_Standard.md §7):
|
|
* labels Montserrat 700, uppercase, letter-spaced; values/dimensions JetBrains Mono 700
|
|
* strokes INK; brand accent GOLD/KICK; limits and warnings RED (dashed)
|
|
* draw at viewBox width 700 for full-width figures, ~240 for step side-figures
|
|
"""
|
|
from .brand import INK, GOLD, KICK, MUTE, CREAM, LINE, RED, REDBG, GRN, GRNBG, BLU, GRY # noqa: F401
|
|
|
|
|
|
def T(x, y, s, size=8, w=600, fill=INK, anchor="start", rot=None, fam="Montserrat", ls=0.4, halo=False):
|
|
"""One <text> element. halo=True adds a white outline so labels read over linework."""
|
|
r = f' transform="rotate({rot} {x} {y})"' if rot is not None else ""
|
|
h = ' stroke="#fff" stroke-width="3" paint-order="stroke"' if halo else ""
|
|
return (f'<text x="{x:.1f}" y="{y:.1f}" font-family="{fam}" font-size="{size}" font-weight="{w}" '
|
|
f'fill="{fill}" text-anchor="{anchor}" letter-spacing="{ls}"{r}{h}>{s}</text>')
|
|
|
|
|
|
def svg_open(w, h, grid=False, prefix="f"):
|
|
"""Open an <svg> at width 100% with shared markers; grid=True adds the faint drafting grid."""
|
|
s = f'<svg viewBox="0 0 {w} {h}" width="100%" xmlns="http://www.w3.org/2000/svg">' + markers(prefix)
|
|
if grid:
|
|
s += f'<rect width="{w}" height="{h}" fill="url(#{prefix}grid)"/>'
|
|
return s
|
|
|
|
|
|
def markers(p="f"):
|
|
"""Arrowheads (#{p}a ink, #{p}g gold), hatches (#{p}h grey, #{p}r red) and grid (#{p}grid)."""
|
|
return (f'<defs><marker id="{p}a" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">'
|
|
f'<path d="M0,1.5 L10,5 L0,8.5 z" fill="{INK}"/></marker>'
|
|
f'<marker id="{p}g" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse">'
|
|
f'<path d="M0,1 L10,5 L0,9 z" fill="{KICK}"/></marker>'
|
|
f'<pattern id="{p}h" width="6" height="6" patternUnits="userSpaceOnUse" patternTransform="rotate(45)">'
|
|
f'<line x1="0" y1="0" x2="0" y2="6" stroke="#CFC7BC" stroke-width="1.2"/></pattern>'
|
|
f'<pattern id="{p}r" width="5" height="5" patternUnits="userSpaceOnUse" patternTransform="rotate(45)">'
|
|
f'<line x1="0" y1="0" x2="0" y2="5" stroke="{RED}" stroke-width="1.3"/></pattern>'
|
|
f'<pattern id="{p}grid" width="14" height="14" patternUnits="userSpaceOnUse">'
|
|
f'<path d="M14 0H0V14" fill="none" stroke="#EFEAE3" stroke-width="0.7"/></pattern></defs>')
|
|
|
|
|
|
def dim_h(x1, x2, y, label, ext_from=None, p="f", size=8.5):
|
|
"""Horizontal dimension line from x1 to x2 at height y with centred label.
|
|
ext_from: y the extension lines start from (the feature edge)."""
|
|
o = []
|
|
if ext_from is not None:
|
|
for x in (x1, x2):
|
|
o.append(f'<line x1="{x}" y1="{ext_from}" x2="{x}" y2="{y + (4 if y > ext_from else -4)}" stroke="{MUTE}" stroke-width=".6"/>')
|
|
o.append(f'<line x1="{x1}" y1="{y}" x2="{x2}" y2="{y}" stroke="{INK}" stroke-width=".8" marker-start="url(#{p}a)" marker-end="url(#{p}a)"/>')
|
|
o.append(T((x1 + x2) / 2, y - 4, label, size=size, w=700, anchor="middle", fam="JetBrains Mono", ls=0, halo=True))
|
|
return "".join(o)
|
|
|
|
|
|
def dim_v(x, y1, y2, label, ext_from=None, p="f", size=8.5):
|
|
"""Vertical dimension line from y1 to y2 at x, label rotated alongside."""
|
|
o = []
|
|
if ext_from is not None:
|
|
for y in (y1, y2):
|
|
o.append(f'<line x1="{ext_from}" y1="{y}" x2="{x + (4 if x > ext_from else -4)}" y2="{y}" stroke="{MUTE}" stroke-width=".6"/>')
|
|
o.append(f'<line x1="{x}" y1="{y1}" x2="{x}" y2="{y2}" stroke="{INK}" stroke-width=".8" marker-start="url(#{p}a)" marker-end="url(#{p}a)"/>')
|
|
cy = (y1 + y2) / 2
|
|
o.append(T(x - 5, cy, label, size=size, w=700, anchor="middle", fam="JetBrains Mono", ls=0, rot=-90, halo=True))
|
|
return "".join(o)
|
|
|
|
|
|
def tag(x, y, t, r=10):
|
|
"""Gold callout bubble matching the drawing schedule tags (B-1, F-1 …)."""
|
|
return (f'<circle cx="{x}" cy="{y}" r="{r}" fill="{GOLD}" stroke="{INK}" stroke-width=".8"/>'
|
|
+ T(x, y + 3, t, size=7, w=800, anchor="middle", ls=0))
|