symbol_sweep
Find every instance of a repeated plan symbol from a single seed; sweep the whole sheet or set and get match centers with scores, or commit matches as takeoff count markers.
Instructions
Find EVERY instance of a repeated plan symbol from ONE example — drains, thresholds, fixtures, transition markers: marquee a tight seed_rect around a single instance and the vector linework is searched for every other placement of that same segment cluster. Deterministic geometry, not vision: each placement scores as the length-weighted fraction of the seed's segments reproduced within tolerance_px, under translation plus 0/90/180/270 rotation and mirroring (symbols rotate on plans — both ON by default; turn them off to pin orientation). Score ≥ 0.92 is a match; the 0.75–0.92 band comes back in withheld with a reason — a near-match is a question you answer by LOOKING (view_sheet at its at), never a silent commit and never a silent drop. The seed's own location is reported in seed and never double-committed. Work is capped and the cap is disclosed: a reply with candidates.dropped > 0 says exactly that some placements were never scored — tighten the seed rect around more distinctive geometry rather than trusting a truncated count. Marquee discipline: the rect must hug ONE instance — only segments FULLY inside it define the symbol, so a loose rect that swallows wall linework fingerprints the wall, not the symbol. scope "set" sweeps the WHOLE working set, counting on PLAN-role sheets only (the sheet graph decides): a symbol drawn in a detail, legend, or schedule is a reference drawing and never counts itself — which is also how you seed from one: marquee the assembly on the detail sheet and its plan-sheet occurrences are counted while the detail stays excluded (the exclusion disclosed in skipped, per-sheet results with per-sheet caps and wall-clock in sheets). Scale across sheets: the fingerprint is size-true and is never scale-SEARCHED, so a detail drawn at 1-1/2" = 1'-0" is 12× the size of the same mark on a 1/8" plan — when BOTH sheets have a scale set, the exact ratio is computed from them and the seed is resized before matching (reported per sheet as scaled); when a scale is missing, the sweep runs at 1:1 and SAYS so (scale_assumed), because an unknown ratio plus a zero count is not evidence of absence. Seeding from a detail/legend/schedule sheet REFUSES outright until both scales are set — that is the case where an unstated ratio silently finds nothing. commit: true (requires condition) commits every match center as an EA count marker through the same path as place_count — the whole sweep (set-wide included) is ONE undo step, each marker carries origin.method "symbol_sweep" with its score, transform, and seed source, and withheld placements are NEVER committed. The COUNT is scale-free (EA), but matching across sheets of different scales is not — set_scale on the sheets involved is what turns the ratio from an assumption into arithmetic. After any batch commit, LOOK at what landed — view_sheet {overlay: true} over the swept area — and audit the markers against the drawing before trusting the EA total. Coordinates are image px at render scale 2.0: PDF pt × 2, origin top-left, y down (the browser canvas's native space). Sheet payloads carry dims in both px and pt.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| scope | No | "sheet" = this sheet only; "set" = every PLAN-role sheet in the working set (needs a text layer for the sheet graph; non-plan sheets are excluded and disclosed) | sheet |
| sheet | Yes | The sheet the seed rect sits on — in scope 'set' it may be ANY sheet (a detail/legend seed sheet is fingerprint source only, never counted) | |
| commit | No | Commit every MATCH center as one EA count marker (withheld placements never commit) | |
| mirror | No | Also match mirrored placements | |
| condition | No | Finish tag to commit match markers under (minted on first use), e.g. 'FD-1'. Required when commit is true | |
| rotations | No | Also match 90/180/270-rotated placements | |
| seed_rect | Yes | Marquee around ONE example instance, [[x0,y0],[x1,y1]] in image px — tight: segments fully inside define the symbol | |
| tolerance_px | No | Endpoint match tolerance in image px (default 2 — CAD jitter, not drift) |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| note | No | ||
| seed | Yes | ||
| found | Yes | Placements that cleared the commit bar — across every swept sheet in set scope | |
| scope | Yes | "sheet" = the swept sheet alone (matches/withheld/candidates at top level); "set" = every PLAN-role sheet in the working set (per-sheet results in sheets[], exclusions in skipped[]) | |
| sheets | No | Set scope only: one entry per swept PLAN-role sheet, load order | |
| matches | No | Sheet scope only. Deterministic reading order (y, then x). The seed's own location is never listed here | |
| skipped | No | Set scope only: every sheet excluded from counting, with role and reason — including the seed's own sheet when it is not a plan | |
| warning | No | Present when the work cap dropped candidates — what a tighter seed rect would recover | |
| ea_total | No | commit mode: the condition's total EA after this call | |
| withheld | No | Sheet scope only. Near-matches in the [0.75, 0.92) band — reported with a reason, NEVER committed. A withheld placement is a question you can answer with view_sheet; a hidden one is a miscount | |
| committed | No | commit mode: count shapes committed — one per match | |
| condition | No | commit mode: the finish tag the markers counted under | |
| shape_ids | No | ||
| candidates | No | Sheet scope only — set scope accounts per sheet in sheets[] |