Add CoordSysLassoSelector for free-form, even-odd coord-space selection#73
Merged
Merged
Conversation
Copilot
AI
changed the title
[WIP] Implement CoordSysLassoSelector for free-form lasso selection
Add Jun 1, 2026
CoordSysLassoSelector for free-form, even-odd coord-space selection
…ox as not applicable in lasso
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR adds a new interaction primitive for
CoordSysRenderer: drag-to-draw free-form lasso selection in coord space, finalized on mouse release and non-editable thereafter. The selected region is represented asPath2DwithWIND_EVEN_ODDso self-intersections resolve by boundary parity (contains(...)behaves correctly for odd-crossing interior).New selector class
CoordSysLassoSelectorinhageldave.jplotter.interaction.kml.CoordSysLassoSelector extends CoordSysViewSelector implements KeyListener.VK_L(customizable via constructorKeyMaskListener).Selection lifecycle + rendering
areaSelected(Path2D).<3points) are discarded.Input handling details
clearLasso().escListenerregistered inregister()/ removed indeRegister().CursorCoordinatoronly:HAND_CURSORCROSSHAIR_CURSORPath semantics + drag decimation
Path2D.Double(Path2D.WIND_EVEN_ODD)andclosePath().>2pxAWT-distance threshold to reduce near-duplicate samples.clearLasso()fully resets overlay/render/state and triggersareaCleared().Original prompt
Overview
Implement a new
CoordSysLassoSelectorclass inhageldave.jplotter.interaction.kmlthat provides free-form lasso selection for the coordinate view ofCoordSysRenderer. The user drags the mouse to draw an arbitrary closed shape; on mouse release the shape is finalised and not editable.File to create
jplotter/src/main/java/hageldave/jplotter/interaction/kml/CoordSysLassoSelector.javaClass hierarchy
CoordSysViewSelectoris in the same package and provides:canvas,jPlotterCanvas,coordsys,overlay(CompleteRenderer),areaBorder(Lines),keyMaskListener,register(),deRegister().Interaction model
areaSelected(Path2D); shape is finalclearLasso())clearLasso()) via aKeyAdapterescListener registered inregister()Key implementation details
State fields
Point decimation in
mouseDraggedOnly append a new point if its AWT pixel distance from the previously recorded point is > 2px. This avoids thousands of near-duplicate points during slow/still drags.
Path construction — WIND_EVEN_ODD
Using
WIND_EVEN_ODDmeans self-intersecting shapes are handled correctly:path.contains(x, y)returns true only if a ray from the point crosses the boundary an odd number of times.mousePressedkeyMaskListener.areKeysPressed()AND click is insidecoordsys.getCoordSysArea().hasSelectionis true: callclearLasso()and return.isDragging = true, clearlassoPoints, add first coord-space point, addlassoLinesto overlay if not already there.mouseDraggedisDraggingmust be true.coordsys.getCoordSysArea()(same clamping logic asCoordSysViewSelector).coordsys.transformAWT2CoordSys.lassoLines: clear all segments, add segments for consecutivelassoPoints, add one preview-close segment from last point back tolassoPoints.get(0)usingcolorScheme.getColor2()or a distinct color.areaSelectedOnGoing(calculateSelectedArea())andjPlotterCanvas.scheduleRepaint().mouseReleasedisDraggingmust be true.isDragging = false.lassoPoints.size() < 3: callclearLasso()and return (degenerate selection).lassoLinesfinal outline (solid close segment, same color as rest of outline).hasSelection = true.areaSelected(calculateSelectedArea())andjPlotterCanvas.scheduleRepaint().clearLasso()Cursor
mouseMoved: if key mask pressed +hasSelection→HAND_CURSOR; if key mask pressed + no selection →CROSSHAIR_CURSOR; else release cursor viaCursorCoordinator.get(canvas).requestCursor(null, this).keyPressed/keyReleasedfromKeyListenerto call the same cursor-update logic.CursorCoordinator.get(canvas).requestCursor(...)throughout (never set cursor directly on canvas).register()/deRegister()register(): callsuper.register(), then addescListenerandthis(as KeyListener) tocanvasif not already present.deRegister(): callsuper.deRegister(), then removeescListenerandthis.KeyAdapterfield:VK_ESCAPE→clearLasso().Abstract / overridable callbacks