Building Check Overlays#
The built-in @plot_data_view methods (see Display & Report Methods) render
fixed overlays — dimensions, balloons, the grid reference, and so on. When you
write your own 2D check you usually need a different overlay: a green/red
verdict on the entities that passed or failed, an explanatory label, an arrow to
the thing at fault. Re-assembling those from raw plot_data rectangles, texts
and line segments every time is tedious and error-prone.
drawing_tools.helpers.visualization.overlays.verdict is the reusable vocabulary for
exactly that. It is the toolkit the Demo Scenarios are built on, and
it is importable from the installed package so external tools can reuse it too.
Core idea: Viz and anchors#
Every helper returns a Viz — a list of plot_data primitives that also
carries the bounding_rectangle of what it draws. Two consequences:
It concatenates like a list, so you accumulate overlays with
+=and hand the result straight toset_extra_plot_primitives.It is itself an anchor. Every helper accepts, wherever it needs a location, either raw coordinates or an
anchor— a drawing entity (anything with a.bounding_rectangle), a bareBoundingRectangle, or aVizreturned by a previous call. Overlays therefore chain naturally.
from pathlib import Path
import plot_data as pld
from volmdlr.core import BoundingRectangle
from dessia_drawing.core import Drawing
from drawing_tools.config.default_language_configs import DEFAULT_FRENCH_CONFIG, DEFAULT_ENGLISH_CONFIG
from drawing_tools.featured_drawing import FeaturedDrawing
_DATA_DIR = Path("data/json")
drawing = Drawing.from_json(str(_DATA_DIR / "2902060102_--A_DEF01_LH SUPPORT ACCUMULATOR ASSEMBLY.json"))
featured_drawing = FeaturedDrawing(drawing, language_configs=[DEFAULT_FRENCH_CONFIG, DEFAULT_ENGLISH_CONFIG])
featured_sheet = featured_drawing.sheets[1]
balloon = featured_sheet.balloons[0]
def view_by_name(name):
"""Return the sheet view with that name."""
return next(view for view in featured_sheet.views if view.name == name)
def title_bounding_rectangle(view):
"""Union bounding rectangle of a view title's text pieces (a valid anchor)."""
pieces = [piece for line in view.title.text_lines for piece in line.texts]
return BoundingRectangle(
xmin=min(p.bounding_rectangle.xmin for p in pieces),
xmax=max(p.bounding_rectangle.xmax for p in pieces),
ymin=min(p.bounding_rectangle.ymin for p in pieces),
ymax=max(p.bounding_rectangle.ymax for p in pieces),
)
verdict_overlay — the OK/NOK verdict#
verdict_overlay(anchor, *, ok, ...) is the workhorse. It draws, all colored by
the ok verdict (green when True, red when False):
a box around the anchor,
an optional label beside it (a single string, or several lines),
a ✓ / ✗ glyph at a configurable corner.
from drawing_tools.helpers.visualization.overlays.verdict import verdict_overlay
frame = balloon.symbol.frame.bounding_rectangle
passed = verdict_overlay(frame, ok=True) # green box + ✓
failed = verdict_overlay(frame, ok=False, label=["BOM", "A3"]) # red box + stacked label + ✗
Appearance is grouped into small config dataclasses — VerdictBoxConfig (box
offsets, opacity, stroke), VerdictLabelConfig (label side, gap, typography,
inter-line spacing) and VerdictGlyphConfig (glyph corner, size, and whether it
anchors on the box or on the label):
from drawing_tools.helpers.visualization.overlays.verdict import (
VerdictBoxConfig,
VerdictGlyphConfig,
VerdictLabelConfig,
)
overlay = verdict_overlay(
frame,
ok=False,
label="wrong zone",
box_config=VerdictBoxConfig(opacity=0.12, line_width=1.8),
label_config=VerdictLabelConfig(side="below", gap=2.0),
glyph_config=VerdictGlyphConfig(corner="bottom-center", on="label"),
)
Accumulate one overlay per checked entity into set_extra_plot_primitives and
you have an annotated check visualization. Here every balloon gets its glyph
below the box (corner="bottom-center" instead of the default middle-right),
the first balloon is flagged failing with a label, and — to show that a verdict
wraps any bounding rectangle — the COUPE A2-A2 view title is checked too:
from drawing_tools.helpers.visualization.overlays.verdict import VerdictGlyphConfig
glyph_below = VerdictGlyphConfig(corner="bottom-center")
extras = []
for index, balloon in enumerate(featured_sheet.balloons):
frame = balloon.symbol.frame.bounding_rectangle
passed = index != 0 # flag the first balloon as failing, for illustration
extras += verdict_overlay(
frame, ok=passed, label=None if passed else "wrong zone", glyph_config=glyph_below
)
title = title_bounding_rectangle(view_by_name("COUPE A2-A2"))
extras += verdict_overlay(title, ok=True, label="view title", glyph_config=glyph_below)
featured_sheet.set_extra_plot_primitives(extras)
featured_sheet.plot_data("balloons_check.html") # or .plot() to open a browser
Source: 2902060102_–A_DEF01_LH SUPPORT ACCUMULATOR ASSEMBLY.json, Sheet 1 — balloons checked (first one failing) plus the COUPE A2-A2 title
callout — point at a target from a distance#
When the label cannot sit on the entity (a tiny title-block cell, a token buried
in the cartouche), callout(target, label, *, color, ...) places the label block
away from the target and draws an arrow from the block to the target’s edge.
Unlike verdict_overlay the color is free — callouts are often informational
(orange, blue) rather than strictly pass/fail — and an optional status adds a
glyph on the label.
Here a two-line note is placed in a clear area above a balloon (the near
anchor) and an arrow points down to the balloon; status="WARN" adds a ⚠ glyph:
from drawing_tools.helpers.visualization.overlays.verdict import callout, ORANGE, VerdictLabelConfig
balloon_box = featured_sheet.balloons[0].symbol.frame.bounding_rectangle
label_spot = BoundingRectangle( # a clear band ~25-40 mm above the balloon
xmin=balloon_box.xmin,
xmax=balloon_box.xmax,
ymin=balloon_box.ymax + 25,
ymax=balloon_box.ymax + 40,
)
extras = callout(
balloon_box,
["check this balloon", "against the BOM"],
color=ORANGE,
status="WARN",
near=label_spot,
label_config=VerdictLabelConfig(side="above", line_gap=10.0), # space the two lines out
)
featured_sheet.set_extra_plot_primitives(list(extras))
featured_sheet.plot_data("balloon_callout.html") # or .plot() to open a browser
Source: 2902060102_–A_DEF01_LH SUPPORT ACCUMULATOR ASSEMBLY.json, Sheet 1 — a WARN callout above a balloon
The safety_class demo (Safety class — drawing vs BOM) is another worked
example: its entire overlay is a single callout pointing from an explanatory
label down to the safety-class token in the title block.
link — a verdict on a relation between two entities#
link(source, target, *, status=..., ...) judges a relation (“this references
that”): it boxes both elements and connects them edge-to-edge with an arrow, with
an optional glyph riding the arrow. The color can be given freely or derived from
status (green / red / orange for OK / NOK / WARN).
Here the B2 section-line indicator is linked to the COUPE B2-B2 view it
names — the exact check the section_lines demo runs:
from drawing_tools.helpers.visualization.overlays.verdict import link
b2_indicator = next(
indicator
for view in featured_sheet.views
for indicator in (view.section_line_indicators or [])
if (indicator.identifier_info.identifier or indicator.identifier_info.letter) == "B2"
)
source_box = b2_indicator.source_entities[0].bounding_rectangle
target_box = title_bounding_rectangle(view_by_name("COUPE B2-B2"))
extras = link(source_box, target_box, status="OK") # two green boxes + arrow + ✓
featured_sheet.set_extra_plot_primitives(list(extras))
featured_sheet.plot_data("section_line_link.html") # or .plot() to open a browser
Source: 2902060102_–A_DEF01_LH SUPPORT ACCUMULATOR ASSEMBLY.json, Sheet 1 — B2 indicator linked to the COUPE B2-B2 view title
The section_lines demo (Section lines — cross-reference with views) applies this to
every indicator on a sheet, flagging any that resolve to no view.
Low-level helpers#
The three composites above cover most checks, but the primitives they are built
from are public too, for overlays that do not fit the mould. Each takes raw
coordinates or an anchor and returns a Viz:
rectangle— a colored rectangle from coordinates or around an anchor, with per-side outward offsets.text— a text primitive, optionally anchored beside another element (near=/side=) and optionally framed.arrow— a straight arrow (shaft + head) between two points or two anchors.status_symbol— a ✓ / ✗ / ⚠ glyph at a corner of an anchor.stacked_texts— several text lines placed as one block beside an anchor.highlight/highlight_text— a symmetric-padding highlight around an entity, or hugging a text’s estimated footprint.estimate_text_bbox/closest_edge_point— the geometry helpers used to place labels and anchor arrow endpoints.
A semantic palette (GREEN, RED, ORANGE, BLUE, PURPLE,
YELLOW_FILL) and the glyph constants (CHECK_MARK, CROSS_MARK,
WARN_MARK) round out the module.
Tip
For end-to-end examples that combine these overlays with real checks against a BOM or the drawing itself, see the Demo Scenarios.