Section Line Indicators#
from pathlib import Path
from dessia_drawing.core import Drawing
from drawing_tools.config.default_language_configs import DEFAULT_ENGLISH_CONFIG, DEFAULT_FRENCH_CONFIG
from drawing_tools.featured_drawing import FeaturedDrawing
_DATA_DIR = Path("data/json")
drawing = Drawing.from_json(str(_DATA_DIR / "condor/condor_BEAM_ASSY.json"))
featured_drawing = FeaturedDrawing(drawing, language_configs=[DEFAULT_FRENCH_CONFIG, DEFAULT_ENGLISH_CONFIG])
featured_sheet = featured_drawing.sheets[3]
featured_view = featured_sheet.views[3]
featured_view.plot_data_section_lines().plot()
featured_sheet.plot_data_section_lines().plot()
Section line indicators are symbols on technical drawings that show where a section cut or auxiliary view is taken. Drawing Tools detects them automatically and provides structured access to their properties.
See also
For a complete working example demonstrating section line detection, see the script
scripts/section_lines_and_auxiliary_view_indicators.py in the repository.
What is a Section Line Indicator?#
A section line indicator consists of:
Two collinear arrows pointing in the same direction, marking the cut line
A letter identifier on each arrow (e.g., “A”, “B”, “K”)
Optionally, a cross-reference to a sheet number (e.g., “4/5” meaning sheet 4 of 5)
A A
| |
------+------------+------
v 4/5 v
These symbols indicate where section views (e.g., COUPE A-A), detail views, or auxiliary views are cut from. The identifier letter corresponds to the view title on the target view (e.g., a section line “A” produces the view “COUPE A-A”).
Accessing Section Line Indicators#
Section line indicators are detected automatically on each FeaturedView:
for sheet in featured_drawing.sheets:
for view in sheet.views:
for indicator in view.section_line_indicators:
info = indicator.identifier_info
print(f"{info.identifier} cross_ref={info.cross_reference} "
f"detection_source={indicator.detection_source}")
SectionLineIndicator Properties#
Each SectionLineIndicator provides:
``identifier_info`` — an
IdentifierInfoobject containing:identifier: full identifier string (e.g.,"A","B2")letter: letter part (e.g.,"A","B")number: numeric suffix orNone(e.g.,2in"B2")cross_reference: sheet cross-reference string (e.g.,"4/5") orNonecross_reference_left: sheet number (e.g.,4) orNonecross_reference_right: total sheets (e.g.,5) orNone
``arrow_locations`` — list of two
Point2Dpositions (the two arrow tips)``arrow_direction`` —
Vector2Dshared direction of both arrows``detection_source`` — how the indicator was detected:
"symbols"— from a single TypeNote annotation with FillArrow leaders"symbols (standalone xref)"— same, but cross-reference was a separate text"composites"— from CompositeEntity arrows paired with standalone TypeNote labels
``source_entities`` — the original dessia_drawing entities
View-Level Visualization#
The following visualization shows section line indicators detected on the “DETAIL 2” view of the BEAM ASSY drawing (Sheet 3). Each indicator is highlighted with a colored bounding rectangle and labels showing its identifier, cross-reference, detection source, and arrow direction.
Source: condor_BEAM_ASSY.json, Sheet 3, DETAIL 2
featured_view = featured_drawing.sheets[3].views[3] # DETAIL 2
featured_view.plot_data_section_lines().plot()
Sheet-Level Visualization#
Section line indicators can also be visualized at the sheet level, showing all indicators across all views on a single sheet:
Source: condor_BEAM_ASSY.json, Sheet 3
featured_sheet = featured_drawing.sheets[3]
featured_sheet.plot_data_section_lines().plot()
Each indicator is assigned a different color from a rotating palette to distinguish overlapping indicators.
Detection Sources#
Section line indicators can be encoded in two different ways in CAD files. Drawing Tools handles both representations transparently:
Symbols (detection_source="symbols"): A single TypeNote annotation carries
both the arrows (as FillArrow leaders) and the text labels. This is the most common
representation.
Composites (detection_source="composites"): Each arrow is a separate
CompositeEntity and the letter labels are standalone TypeNote annotations
positioned nearby. The detector matches labels to arrows by spatial proximity, then
groups arrow pairs by identifier and collinear direction.
Both sources are merged in the section_line_indicators property. You can check
indicator.detection_source to know which representation was used. To see the code
behind the two branches, see Going Further at the end of this page.
Counting Indicators#
# Number of section line indicators in a view
count = featured_view.section_line_indicator_count
# Iterate and filter
indicators_with_xref = [
ind for ind in featured_view.section_line_indicators
if ind.identifier_info.cross_reference is not None
]
Going Further: Inside the Detection#
For readers who want to see how the detector works
Two classes carry this feature, both in view/annotations/section_line_indicator.py:
the feature —
SectionLineIndicator, the value object described above, with itsIdentifierInfo, its arrow locations and direction and itsdetection_source;the detector —
ViewSectionLineDetector, which holds the recipe and itsSectionLineDetectionConfig.FeaturedView.section_line_indicatorsbuilds one per view; the sheet property concatenates the results.
detect_all is one line: the symbols branch plus the composites branch of
Detection Sources. The symbols branch (_extract_from_symbols) walks the view’s
TypeNote annotations and keeps those with exactly two collinear FillArrow leaders
(_get_valid_symbol_arrow_pair) and a duplicated identifier in their texts
(_extract_duplicated_identifier_info, completed by
_complete_identifier_info_with_duplicated_xref). The composites branch is a
four-step pipeline:
def _extract_from_composites(self) -> list[SectionLineIndicator]:
"""Detect section line indicators from CompositeEntity arrows + standalone TypeNote labels.
In this representation, each arrow is a separate CompositeEntity and the letter
labels (e.g., ``"A"``, ``"K 4/5"``) are standalone TypeNote annotations positioned
nearby. Detection follows a four-step pipeline:
1. ``_get_composite_arrow_candidates``: collect CompositeEntity arrows with valid geometry.
2. ``_collect_identifier_notes``: collect TypeNote labels matching the indicator pattern.
3. ``_match_arrows_to_identifiers``: spatially match each label to its nearest arrow.
4. ``_group_identified_arrows``: group arrows by matching identifier + collinear direction.
Then ``_build_indicators_from_groups`` filters valid pairs and builds indicators.
"""
single_arrow_candidates = self._get_composite_arrow_candidates()
if len(single_arrow_candidates) < self.config.min_leaders_for_indicator:
return []
identifier_notes, identifier_infos = self._collect_identifier_notes()
identified_arrows = self._match_arrows_to_identifiers(
identifier_notes, identifier_infos, single_arrow_candidates
)
grouped_identified_arrows = self._group_identified_arrows(identified_arrows)
return self._build_indicators_from_groups(grouped_identified_arrows)
_get_composite_arrow_candidatesreads the arrows drawn asCompositeEntity(collect_composite_arrowsincomposite_arrows.py, shared with the auxiliary view indicators);_collect_identifier_noteskeeps the standalone notes reading as an identifier;_match_arrows_to_identifiersgives each note its nearest arrow;_group_identified_arrowspairs arrows carrying the same identifier whose tips lie on one perpendicular line, and_build_indicators_from_groupskeeps the valid pairs.
The step-by-step walkthrough, with the geometry of each test, is in Section Line Indicator Detection Pipeline.