drawing_tools.view.annotations.symbol.electrical package#

Submodules#

drawing_tools.view.annotations.symbol.electrical.bonding_symbols module#

Electrical bonding symbol — the detected element.

A bonding symbol marks an electrical bonding point on a technical drawing. It looks like a balloon — a circle with a number beside it — but it carries the earth/ground glyph instead of an item number, and several symbols of a drawing share the same number without being related to each other. CATIA exports it as a CompositeEntity whose geometries hold the circle and the glyph, and whose entities hold a bare TypeNote carrying the label (“10”, “47” — the TYPE column of the title-block bonding table).

Everything a bonding symbol is assigned afterwards is exported OUTSIDE that composite and attached on top of the detection, the way Balloon gets its flags and its group: each of the symbol’s own leader arrows is a SEPARATE text-less TypeNote whose leader ends on the circle, and a symbol drawn with NO arrow of its own is stacked against a balloon group and borrows that group’s leaders. The detector fills BondingSymbol.leader_notes and BondingSymbol.balloons after the detection, which the attachments never influence.

Detection lives in drawing_tools.view.annotations.symbol.electrical.view_bonding_symbol_detector.

drawing_tools.view.annotations.symbol.electrical.bonding_symbols.MASTER_GROUP_STATUSES = ('parent', 'isolated')#

Group statuses whose touched balloon is itself the master (it carries the group’s leaders).

drawing_tools.view.annotations.symbol.electrical.bonding_symbols.CAPTION_LINE_HEIGHT_RATIO = 2.7#

Vertical spacing between the overlay caption lines, as a multiple of the symbol radius, so the caption scales with the glyph instead of colliding on another sheet format. Calibrated on rendered PNGs: the lines collide below 1.7.

class drawing_tools.view.annotations.symbol.electrical.bonding_symbols.BondingSymbol(source_entity: Entity, circle: Edge, label_symbol: TextSearchable | None = None)#

Bases: object

Wrapper for a bonding symbol composite: the earth glyph, its label and its leader arrows.

A bonding symbol requires an electrical bonding (metal-to-metal continuity) at the points its leader arrows designate. It is drawn as a circle enclosing the earth glyph, with a number beside it — the bonding TYPE of the title-block METALLISATION table.

__init__(source_entity: Entity, circle: Edge, label_symbol: TextSearchable | None = None) None#

Initialize a bonding symbol from the entity it was detected on.

The detector fills two attributes afterwards, mutually exclusive by convention: leader_notes, the text-less notes carrying the symbol’s own leader arrows, and balloons, the group it is stacked against (closest balloon first) whose leaders it borrows when it has none of its own.

Parameters:
  • source_entity – The entity holding the circle, the earth glyph and the label — a CompositeEntity for the only export shape known so far, hence the loose type: a future detection branch may build symbols from something else.

  • circle – The full-circle edge of the symbol.

  • label_symbol – The text entity carrying the label, when the symbol has one.

Raises:

ValueError – If circle is not a full circle — every geometric property of the symbol reads it, so the mistake is reported here rather than at the first access.

leader_notes: list[Symbol]#
balloons: list[Balloon]#
property center: Point2D#

Return the circle center — where the symbol’s own leader arrows converge.

property radius: float#

Return the circle radius.

property bounding_rectangle: BoundingRectangle#

Return the bounding rectangle of the CIRCLE alone — narrower than the drawn symbol.

Deliberate: it is the box the overlay draws on. The label keeps its own (label_symbol.bounding_rectangle) and the whole drawn symbol — circle, glyph and label together — is source_entity.bounding_rectangle.

property label: str#

Return the text written NEXT TO the circle (“10”, “47”…), “” when none was found.

The circle itself carries no text: the label is a separate note (label_symbol). Semantically this text is the bonding TYPE of the title-block bonding table, not an identifier of this symbol: several bonding symbols carry the same one without being related to each other.

property leaders: list[Leader]#

Return the leader arrows of the symbol itself, one per designated bonding point.

Same contract as the section-line indicators’ leaders: Leader objects, whatever entity carried them — here one text-less note per arrow (leader_notes, filled by the detector after the detection).

property leader_count: int#

Return the number of leader arrows the symbol carries ITSELF.

A bonding symbol either carries its own arrows, or is stacked against a balloon group and borrows its leaders — never both, a convention the detector applies when it attaches them. So a count of 0 next to a non-empty balloons means the arrows are the group’s, and their number is master_balloon_leader_count. Read those two rather than deciding for yourself which one takes precedence: the day a drawing shows a symbol legitimately carrying both, the convention changes in one place and every consumer follows.

property balloon_count: int#

Return the number of balloons of the group the symbol is stacked against.

0 both when the symbol stands alone and when it carries its own arrows: a symbol that designates its points itself is never attached to a neighbouring balloon.

property master_balloon: Balloon | None#

Return the balloon carrying the attached group’s leaders, None when there is no single one.

The parent of the group when the symbol touches a child balloon, the touched balloon itself when it is a parent or an isolated balloon. None both when no balloon is attached and when the group is "undefined" — a group with no leader-carrying balloon, or several, has no single master, and claiming one would invent a fact.

property master_balloon_leader_count: int#

Return the leader count of the master balloon, 0 when there is no master.

Read through master_balloon so a single place resolves the master. Balloon.effective_leader_count is deliberately not used: it answers the child’s own question and cannot express “this group has no single master”.

property overlay_lines: list[str]#

the label, then what designates its bonding points.

The own-leader count is always stated — reading “Owns 0 leaders” above the group lines is what says the symbol borrows the group’s leaders. The group lines only appear when the symbol is stacked against balloons. The caption drawn on the sheet and tooltip both read these lines, so the two can never diverge.

Type:

Return the overlay caption lines

property tooltip: str#

overlay_lines joined, as shown on hover.

Type:

Return the overlay tooltip

overlay_primitives(color: Color | None = None) list#

Build the diagnostic overlay of this bonding symbol, every part in the same color.

Draws a rectangle around the circle carrying tooltip, the symbol’s own leader arrows — so it reads at a glance which bonding points the symbol designates — and the overlay_lines caption, so the assignment is readable without hovering, spaced by CAPTION_LINE_HEIGHT_RATIO.

Parameters:

color – Overlay color. Defaults to blue; callers rendering several symbols pass one color per symbol from a palette.

Returns:

List of plot_data primitives.

leader_overlay_primitives(color: Color | None = None) list#

Redraw the symbol’s own leader arrows in the overlay color.

Parameters:

color – Overlay color (default: blue).

Returns:

List of plot_data primitives, empty when the symbol carries no leader.

__repr__() str#

Return a string representation of the bonding symbol.

drawing_tools.view.annotations.symbol.electrical.view_bonding_symbol_detector module#

View-level detection of electrical bonding symbols.

Recognizes the earth/ground glyph geometrically — a circle, a vertical segment from its center and three rows of horizontal bars — and reads the label beside it. The detected element is BondingSymbol.

On top of the detection — which they never influence — the detector then attaches to each symbol what CATIA exported outside its composite: the symbol’s own leader arrows (one text-less TypeNote each, whose leader ends on the circle), and the balloon group the symbol is stacked against when it carries no arrow of its own and borrows the group’s leader instead.

drawing_tools.view.annotations.symbol.electrical.view_bonding_symbol_detector.COMPOSITE_OPTIONS = <dessia_drawing.collectors.options.ViewCollectorOptions object>#

The CompositeEntity annotations of a view — a bonding symbol is exported as one.

drawing_tools.view.annotations.symbol.electrical.view_bonding_symbol_detector.TYPE_NOTE_OPTIONS = <dessia_drawing.collectors.options.ViewCollectorOptions object>#

Top-level TypeNote symbols of a view — the leader arrows of a bonding symbol live there.

class drawing_tools.view.annotations.symbol.electrical.view_bonding_symbol_detector.BondingSymbolDetectionConfig(full_circle_count: int = 1, bar_row_count: int = 3, center_touch_tolerance: float = 0.15, direction_tolerance: float = 0.1, bar_row_tolerance: float = 0.15, max_composite_text_count: int = 1, leader_end_tolerance: float = 0.35, balloon_attachment_gap: float = 1.5)#

Bases: object

Tuning of ViewBondingSymbolDetector.

The proximity thresholds are fractions of the symbol’s circle radius, so they hold at any scale; direction_tolerance is the exception — it is an absolute coordinate offset, because that is what volmdlr’s vertical / horizontal tests take. Directions are tested in SHEET space: the earth symbol is drawn upright, and a rotated glyph is not detected.

Parameters:
  • full_circle_count – Exact number of full circles the composite must draw — one, the circle enclosing the earth glyph.

  • bar_row_count – Exact number of bar rows the earth glyph must show — three in the standard symbol, each row possibly exported as two half-bars.

  • center_touch_tolerance – Max distance between the circle center and the endpoint of the glyph’s vertical segment touching it, as a fraction of the radius.

  • direction_tolerance – Tolerance of the vertical / horizontal tests, in drawing units — it is the accepted offset between a segment’s endpoints on the other axis (volmdlr’s is_vertical / is_horizontal), so a longer segment is judged more strictly.

  • bar_row_tolerance – Max offset between two bars for them to count as the same row, as a fraction of the radius.

  • max_composite_text_count – Max number of text-bearing ENTITIES in the composite (not leaf texts): a bonding composite holds one, its label. The title-block bonding table draws the same glyph next to its TYPE / NOMBRE columns and holds many, so this bound rejects it.

  • leader_end_tolerance – Max distance between a leader end and the circle boundary, as a fraction of the radius, for the leader’s note to be attached to the symbol. Measured on the reference drawings: an attached leader ends exactly ON the circle (0.00 radius), the nearest other symbol is at 43 radii.

  • balloon_attachment_gap – Max gap between the symbol’s circle and a balloon’s circle, as a fraction of the symbol radius, for the symbol to count as stacked against that balloon. Measured on the reference drawings: real gaps of stacked pairs are 0.07 to 1.07 radius, the nearest balloon of a symbol standing alone is at 4.8 radii.

full_circle_count: int = 1#
bar_row_count: int = 3#
center_touch_tolerance: float = 0.15#
direction_tolerance: float = 0.1#
bar_row_tolerance: float = 0.15#
max_composite_text_count: int = 1#
leader_end_tolerance: float = 0.35#
balloon_attachment_gap: float = 1.5#
__init__(full_circle_count: int = 1, bar_row_count: int = 3, center_touch_tolerance: float = 0.15, direction_tolerance: float = 0.1, bar_row_tolerance: float = 0.15, max_composite_text_count: int = 1, leader_end_tolerance: float = 0.35, balloon_attachment_gap: float = 1.5) None#
class drawing_tools.view.annotations.symbol.electrical.view_bonding_symbol_detector.ViewBondingSymbolDetector(view: View, config: BondingSymbolDetectionConfig | None = None, balloons_provider: Callable[[], list[Balloon]] | None = None)#

Bases: object

Detect electrical bonding symbols in a view.

Pipeline:

  1. Every CompositeEntity of the view whose geometries contain one full circle and the earth glyph inside it (a vertical segment from the center plus its horizontal bars) becomes a symbol.

  2. The label is the single text of that same composite — the CAD grouping is authoritative, so no proximity search is needed (checked on the whole reference drawing: the label is nested in the composite for all of its symbols).

  3. The text-less TypeNote symbols whose leader ends on the circle are attached to the symbol as its own leader arrows (BondingSymbol.leader_notes).

  4. For a symbol left without any arrow of its own, the balloon group whose circle it is stacked against is attached as BondingSymbol.balloons — that group’s leaders are the ones it borrows. Steps 3 and 4 are exclusive by convention: at most one is filled.

Usage:

detector = ViewBondingSymbolDetector(view)
bonding_symbols = detector.bonding_symbols   # cached_property
__init__(view: View, config: BondingSymbolDetectionConfig | None = None, balloons_provider: Callable[[], list[Balloon]] | None = None) None#

Initialize the detector.

Parameters:
  • view – A dessia_drawing View object to analyze.

  • config – Detection parameters. Uses defaults if not provided.

  • balloons_provider – Returns the view’s already-analyzed balloons, so the Featured layer can share what it computed. A callable rather than the list itself: balloons are only needed once a symbol has been detected, and asking the Featured layer for them costs a full balloon analysis (and, through it, title parsing, which requires language configs). Analyzed here when not provided.

property bonding_symbols: list[BondingSymbol]#

All detected bonding symbols (computed once on first access).

detect_all() list[BondingSymbol]#

Detect this view’s bonding symbols, then attach what each one is assigned.

Steps:

  1. Extract the symbols from the view’s composite entities (the only source known so far).

  2. Attach to each of them the leader arrows ending on its circle.

  3. ONLY for a symbol left without any arrow of its own, attach the balloon group it is stacked against, whose leaders it then borrows.

Making step 3 exclusive of step 2 is a CONVENTION taken here, not a law measured on drawings: none seen so far carries both, and a balloon merely sitting next to a symbol that already designates its own points would be a neighbour rather than a stacking relationship. Should a drawing turn up where a symbol legitimately has both, drop the condition below and let the two coexist.

Returns:

List of detected BondingSymbol instances.

Module contents#

Electrical symbols of a technical drawing.

Home of the symbols an electrical requirement puts on a drawing — bonding for now, the earth / ground glyph in its circle; the family is meant to grow (shielding, grounding, continuity…).

class drawing_tools.view.annotations.symbol.electrical.BondingSymbol(source_entity: Entity, circle: Edge, label_symbol: TextSearchable | None = None)#

Bases: object

Wrapper for a bonding symbol composite: the earth glyph, its label and its leader arrows.

A bonding symbol requires an electrical bonding (metal-to-metal continuity) at the points its leader arrows designate. It is drawn as a circle enclosing the earth glyph, with a number beside it — the bonding TYPE of the title-block METALLISATION table.

__init__(source_entity: Entity, circle: Edge, label_symbol: TextSearchable | None = None) None#

Initialize a bonding symbol from the entity it was detected on.

The detector fills two attributes afterwards, mutually exclusive by convention: leader_notes, the text-less notes carrying the symbol’s own leader arrows, and balloons, the group it is stacked against (closest balloon first) whose leaders it borrows when it has none of its own.

Parameters:
  • source_entity – The entity holding the circle, the earth glyph and the label — a CompositeEntity for the only export shape known so far, hence the loose type: a future detection branch may build symbols from something else.

  • circle – The full-circle edge of the symbol.

  • label_symbol – The text entity carrying the label, when the symbol has one.

Raises:

ValueError – If circle is not a full circle — every geometric property of the symbol reads it, so the mistake is reported here rather than at the first access.

leader_notes: list[Symbol]#
balloons: list[Balloon]#
property center: Point2D#

Return the circle center — where the symbol’s own leader arrows converge.

property radius: float#

Return the circle radius.

property bounding_rectangle: BoundingRectangle#

Return the bounding rectangle of the CIRCLE alone — narrower than the drawn symbol.

Deliberate: it is the box the overlay draws on. The label keeps its own (label_symbol.bounding_rectangle) and the whole drawn symbol — circle, glyph and label together — is source_entity.bounding_rectangle.

property label: str#

Return the text written NEXT TO the circle (“10”, “47”…), “” when none was found.

The circle itself carries no text: the label is a separate note (label_symbol). Semantically this text is the bonding TYPE of the title-block bonding table, not an identifier of this symbol: several bonding symbols carry the same one without being related to each other.

property leaders: list[Leader]#

Return the leader arrows of the symbol itself, one per designated bonding point.

Same contract as the section-line indicators’ leaders: Leader objects, whatever entity carried them — here one text-less note per arrow (leader_notes, filled by the detector after the detection).

property leader_count: int#

Return the number of leader arrows the symbol carries ITSELF.

A bonding symbol either carries its own arrows, or is stacked against a balloon group and borrows its leaders — never both, a convention the detector applies when it attaches them. So a count of 0 next to a non-empty balloons means the arrows are the group’s, and their number is master_balloon_leader_count. Read those two rather than deciding for yourself which one takes precedence: the day a drawing shows a symbol legitimately carrying both, the convention changes in one place and every consumer follows.

property balloon_count: int#

Return the number of balloons of the group the symbol is stacked against.

0 both when the symbol stands alone and when it carries its own arrows: a symbol that designates its points itself is never attached to a neighbouring balloon.

property master_balloon: Balloon | None#

Return the balloon carrying the attached group’s leaders, None when there is no single one.

The parent of the group when the symbol touches a child balloon, the touched balloon itself when it is a parent or an isolated balloon. None both when no balloon is attached and when the group is "undefined" — a group with no leader-carrying balloon, or several, has no single master, and claiming one would invent a fact.

property master_balloon_leader_count: int#

Return the leader count of the master balloon, 0 when there is no master.

Read through master_balloon so a single place resolves the master. Balloon.effective_leader_count is deliberately not used: it answers the child’s own question and cannot express “this group has no single master”.

property overlay_lines: list[str]#

the label, then what designates its bonding points.

The own-leader count is always stated — reading “Owns 0 leaders” above the group lines is what says the symbol borrows the group’s leaders. The group lines only appear when the symbol is stacked against balloons. The caption drawn on the sheet and tooltip both read these lines, so the two can never diverge.

Type:

Return the overlay caption lines

property tooltip: str#

overlay_lines joined, as shown on hover.

Type:

Return the overlay tooltip

overlay_primitives(color: Color | None = None) list#

Build the diagnostic overlay of this bonding symbol, every part in the same color.

Draws a rectangle around the circle carrying tooltip, the symbol’s own leader arrows — so it reads at a glance which bonding points the symbol designates — and the overlay_lines caption, so the assignment is readable without hovering, spaced by CAPTION_LINE_HEIGHT_RATIO.

Parameters:

color – Overlay color. Defaults to blue; callers rendering several symbols pass one color per symbol from a palette.

Returns:

List of plot_data primitives.

leader_overlay_primitives(color: Color | None = None) list#

Redraw the symbol’s own leader arrows in the overlay color.

Parameters:

color – Overlay color (default: blue).

Returns:

List of plot_data primitives, empty when the symbol carries no leader.

__repr__() str#

Return a string representation of the bonding symbol.

class drawing_tools.view.annotations.symbol.electrical.BondingSymbolDetectionConfig(full_circle_count: int = 1, bar_row_count: int = 3, center_touch_tolerance: float = 0.15, direction_tolerance: float = 0.1, bar_row_tolerance: float = 0.15, max_composite_text_count: int = 1, leader_end_tolerance: float = 0.35, balloon_attachment_gap: float = 1.5)#

Bases: object

Tuning of ViewBondingSymbolDetector.

The proximity thresholds are fractions of the symbol’s circle radius, so they hold at any scale; direction_tolerance is the exception — it is an absolute coordinate offset, because that is what volmdlr’s vertical / horizontal tests take. Directions are tested in SHEET space: the earth symbol is drawn upright, and a rotated glyph is not detected.

Parameters:
  • full_circle_count – Exact number of full circles the composite must draw — one, the circle enclosing the earth glyph.

  • bar_row_count – Exact number of bar rows the earth glyph must show — three in the standard symbol, each row possibly exported as two half-bars.

  • center_touch_tolerance – Max distance between the circle center and the endpoint of the glyph’s vertical segment touching it, as a fraction of the radius.

  • direction_tolerance – Tolerance of the vertical / horizontal tests, in drawing units — it is the accepted offset between a segment’s endpoints on the other axis (volmdlr’s is_vertical / is_horizontal), so a longer segment is judged more strictly.

  • bar_row_tolerance – Max offset between two bars for them to count as the same row, as a fraction of the radius.

  • max_composite_text_count – Max number of text-bearing ENTITIES in the composite (not leaf texts): a bonding composite holds one, its label. The title-block bonding table draws the same glyph next to its TYPE / NOMBRE columns and holds many, so this bound rejects it.

  • leader_end_tolerance – Max distance between a leader end and the circle boundary, as a fraction of the radius, for the leader’s note to be attached to the symbol. Measured on the reference drawings: an attached leader ends exactly ON the circle (0.00 radius), the nearest other symbol is at 43 radii.

  • balloon_attachment_gap – Max gap between the symbol’s circle and a balloon’s circle, as a fraction of the symbol radius, for the symbol to count as stacked against that balloon. Measured on the reference drawings: real gaps of stacked pairs are 0.07 to 1.07 radius, the nearest balloon of a symbol standing alone is at 4.8 radii.

full_circle_count: int = 1#
bar_row_count: int = 3#
center_touch_tolerance: float = 0.15#
direction_tolerance: float = 0.1#
bar_row_tolerance: float = 0.15#
max_composite_text_count: int = 1#
leader_end_tolerance: float = 0.35#
balloon_attachment_gap: float = 1.5#
__init__(full_circle_count: int = 1, bar_row_count: int = 3, center_touch_tolerance: float = 0.15, direction_tolerance: float = 0.1, bar_row_tolerance: float = 0.15, max_composite_text_count: int = 1, leader_end_tolerance: float = 0.35, balloon_attachment_gap: float = 1.5) None#
class drawing_tools.view.annotations.symbol.electrical.ViewBondingSymbolDetector(view: View, config: BondingSymbolDetectionConfig | None = None, balloons_provider: Callable[[], list[Balloon]] | None = None)#

Bases: object

Detect electrical bonding symbols in a view.

Pipeline:

  1. Every CompositeEntity of the view whose geometries contain one full circle and the earth glyph inside it (a vertical segment from the center plus its horizontal bars) becomes a symbol.

  2. The label is the single text of that same composite — the CAD grouping is authoritative, so no proximity search is needed (checked on the whole reference drawing: the label is nested in the composite for all of its symbols).

  3. The text-less TypeNote symbols whose leader ends on the circle are attached to the symbol as its own leader arrows (BondingSymbol.leader_notes).

  4. For a symbol left without any arrow of its own, the balloon group whose circle it is stacked against is attached as BondingSymbol.balloons — that group’s leaders are the ones it borrows. Steps 3 and 4 are exclusive by convention: at most one is filled.

Usage:

detector = ViewBondingSymbolDetector(view)
bonding_symbols = detector.bonding_symbols   # cached_property
__init__(view: View, config: BondingSymbolDetectionConfig | None = None, balloons_provider: Callable[[], list[Balloon]] | None = None) None#

Initialize the detector.

Parameters:
  • view – A dessia_drawing View object to analyze.

  • config – Detection parameters. Uses defaults if not provided.

  • balloons_provider – Returns the view’s already-analyzed balloons, so the Featured layer can share what it computed. A callable rather than the list itself: balloons are only needed once a symbol has been detected, and asking the Featured layer for them costs a full balloon analysis (and, through it, title parsing, which requires language configs). Analyzed here when not provided.

property bonding_symbols: list[BondingSymbol]#

All detected bonding symbols (computed once on first access).

detect_all() list[BondingSymbol]#

Detect this view’s bonding symbols, then attach what each one is assigned.

Steps:

  1. Extract the symbols from the view’s composite entities (the only source known so far).

  2. Attach to each of them the leader arrows ending on its circle.

  3. ONLY for a symbol left without any arrow of its own, attach the balloon group it is stacked against, whose leaders it then borrows.

Making step 3 exclusive of step 2 is a CONVENTION taken here, not a law measured on drawings: none seen so far carries both, and a balloon merely sitting next to a symbol that already designates its own points would be a neighbour rather than a stacking relationship. Should a drawing turn up where a symbol legitimately has both, drop the condition below and let the two coexist.

Returns:

List of detected BondingSymbol instances.