Rubber-band selects a freehand drawing from empty space inside its bounding box #224
Labels
No labels
prio_critical
prio_low
type_bug
type_contact
type_issue
type_lead
type_question
type_story
type_task
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
lhumina_code/hero_whiteboard#224
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
A rubber-band selection that covers only the empty area inside a freehand drawing's bounding box selects the drawing, even though it never crosses the ink. It should select a drawing only when the selection rectangle actually overlaps the strokes (this is the rubber-band counterpart of the click/drag fix in #222).
Steps to reproduce
Root cause
crates/hero_whiteboard_admin/static/web/js/whiteboard/tools.js,onMouseUp(selection branch, ~line 845): the rubber-band selects every.objectwhose bounding box (shape.getClientRect()) intersects the selection box. For a freehand drawing the bounding box includes the empty space between strokes, so a rectangle over a blank pocket still matches.Proposed fix
Keep the cheap bounding-box intersection as a pre-filter, but for drawings add a precise test: only select the drawing when the selection rectangle (in world coordinates) actually intersects one of the ink segments. Mirror the world-coordinate segment iteration already used by
_drawingHitByCircle, using a segment-vs-AABB (Liang-Barsky) test against the selection rectangle.Acceptance criteria
Implementation Spec for Issue #224
Objective
A rubber-band selection should select a freehand drawing only when the selection rectangle actually overlaps the ink, not merely the drawing's bounding box.
Root cause
onMouseUp(selection branch, tools.js ~line 845) selects any.objectwhosegetClientRect()(bbox) intersects the selection box. A drawing's bbox includes blank space between strokes.Files to Modify
crates/hero_whiteboard_admin/static/web/js/whiteboard/tools.js-onMouseUpselection loop + two small geometry helpers.Implementation Plan
Step 1: Add segment-vs-rectangle helpers
Files:
crates/hero_whiteboard_admin/static/web/js/whiteboard/tools.js_segIntersectsAABB(x0,y0,x1,y1,minX,minY,maxX,maxY)using Liang-Barsky clipping (returns true if the segment touches the axis-aligned box, including endpoints inside)._drawingIntersectsRect(group, rectWorld): iterate the group's.linepoints in world coords (pts[i] + group.x()/y(), mirroring_drawingHitByCircle) and return true if any segment intersectsrectWorld. Single-point strokes: test the point for containment.Dependencies: none
Step 2: Use the precise test for drawings in the rubber-band loop
Files:
crates/hero_whiteboard_admin/static/web/js/whiteboard/tools.jsonMouseUp, compute the selection box in world coords once:var boxWorld = selectionRect.getClientRect({ relativeTo: layer });.shapes.forEachloop, after the existing bboxKonva.Util.haveIntersection(box, r)pre-filter passes, look upWhiteboardObjects.getObject(shape.id()); if its type isdrawingand!_drawingIntersectsRect(shape, boxWorld), skip it. All other types keep the bbox behaviour.Dependencies: Step 1
Acceptance Criteria
Notes
tension(spline smoothing); testing straight segments between points is a close, acceptable approximation for selection.relativeTo: layer); the cheap screen-space bbox pre-filter is kept to avoid the segment test on every object.Implementation Summary
Changes
crates/hero_whiteboard_admin/static/web/js/whiteboard/tools.js:_segIntersectsAABB(...)(Liang-Barsky segment-vs-axis-aligned-box test) and_drawingIntersectsRect(group, rectWorld), which iterates the drawing's.linepoints in world coords (mirroring_drawingHitByCircle) and returns true only when a stroke segment actually crosses the rectangle.onMouseUprubber-band selection, the world-space selection rectangle (selectionRect.getClientRect({ relativeTo: layer })) is computed once. The cheap screen-space bboxhaveIntersectionstays as a pre-filter; for objects whose type isdrawing, the shape is only selected when_drawingIntersectsRectconfirms the rectangle overlaps the ink. All other object types keep the bbox behaviour.Verification
node --checkpasses.Acceptance criteria