PR-D4: pick support for dynamic feature sources#147
Merged
Conversation
Adds click-to-identify for dynamic-source overlays (own-ship, AIS targets). The map click handler now also hit-tests live IDynamicFeatureSource.CurrentFeatures snapshots and merges those hits into PickReportViewModel, which renders a sectioned 'Dynamic sources' block alongside the existing dataset hits. Highlights: - DynamicSourceHitTester: pure, 12-device-pixel tolerance, point-only in v1, sources walked in registration order, hits ordered by ascending distance. - IDynamicSourcePickService / DynamicSourcePickService: projects raw hits to DynamicPickHit DTOs with localised attribute rows (Position, COG, Heading, SOG, Dimensions, MMSI, Name, Call sign). - IDynamicFeatureSourceRegistry.GetVisibleSourceInstances(): exposes the live source list so the pick path can read CurrentFeatures / Metadata without an extra registration round-trip; hidden sources are excluded. - PickReportViewModel: DynamicHits collection plus HasDynamicHits / HasDatasetPick flags; PickReportView gates the dataset detail region by HasDatasetPick so dynamic-only picks render cleanly. - IPickService.HandlePick(MapInfo?, IReadOnlyList<DynamicPickHit>?) with a default parameter — call sites that only pass MapInfo keep compiling. - All new UI strings via Resources/Strings.resx + Strings.cs. - Design doc: docs/design/dynamic-source-pick.md (Q1–Q6). - Viewer README: 'Picking dynamic features' subsection. - Tests: DynamicSourceHitTesterTests, DynamicSourcePickServiceTests, PickReportViewModelTests dynamic-hit coverage (4 new cases). Out of scope (noted in design doc): selection ring on map, multi- target ARPA viewer, AIS aids-to-navigation / base stations / SAR, CPA / TCPA, server-side MCP exposure of dynamic picks. Build clean (0 errors / 2 pre-existing warnings); dotnet test -c Release green across all suites (2,388 passed, 2 skipped). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Previously the dynamic-source hit tester used a single 12-device-pixel tolerance around the antenna position. When the renderer drew a true-scale hull (zoomed in far enough), most of the visible pictogram fell outside this tolerance — the user had to click within a few pixels of the CCRP cross at the antenna, not just anywhere on the drawn vessel. The hit tester now does a point-in-polygon test against the same 5-vertex hull polygon the renderer composes from DynamicVesselGeometry (length / beam / bow + port offsets) and the feature's heading. The 12-px point tolerance still applies for features without VesselGeometry and as a fallback for the disc-mode pictogram so zoomed-out clicks still pick. Inside-polygon hits report distance 0 so they sort ahead of edge-tolerance hits, keeping the closest-first ordering intact. Tests: two new DynamicSourceHitTester cases (inside-hull at tiny resolution, far miss falls back to point tolerance). Full EncDotNet.S100.Viewer.Tests suite: 441 passed. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributor
Performance Gate✅ PASSED — no regressions. Threshold: 10.0%, MAD multiplier (k): 3.0, retry-zone mult: 2.0× Scenario summary
exchange-set-openIteration statistics
Spans (sum of all iterations)
Metrics
s101-portray-coldIteration statistics
Spans (sum of all iterations)
Metrics
s101-portray-warmIteration statistics
Spans (sum of all iterations)
Metrics
s101-render-warmIteration statistics
Spans (sum of all iterations)
Metrics
s102-coverageIteration statistics
Spans (sum of all iterations)
Metrics
s102-coverage-openIteration statistics
Spans (sum of all iterations)
Metrics
s102-coverage-render-largeIteration statistics
Spans (sum of all iterations)
Metrics
s124-vectorIteration statistics
Spans (sum of all iterations)
Metrics
s201-vectorIteration statistics
Spans (sum of all iterations)
Metrics
Generated by EncDotNet.S100.PerfReport gate command |
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.
Closes the click-to-identify gap for dynamic-source overlays shipped in PR-D3 (#142). The map click handler now hit-tests live
IDynamicFeatureSource.CurrentFeaturessnapshots in addition to the dataset/portrayal pipeline, and the Pick Report panel renders a sectioned single list — Dynamic sources block above the existing dataset hits — so a single click reveals every target under the crosshair.What's new
DynamicSourceHitTester— pure, 12-device-pixel tolerance, point-only in v1, sources walked in registration order, hits ordered by ascending distance.IDynamicSourcePickService/DynamicSourcePickService— projects raw hits toDynamicPickHitDTOs with localised attribute rows (Position, COG, Heading, SOG, Dimensions, MMSI, Name, Call sign).IDynamicFeatureSourceRegistry.GetVisibleSourceInstances()— exposes the live source list so the pick path can readCurrentFeatures/Metadatawithout an extra registration round-trip; hidden sources are excluded.PickReportViewModel.DynamicHits+HasDynamicHits/HasDatasetPick—PickReportViewgates the dataset detail region byHasDatasetPickso dynamic-only picks render cleanly.IPickService.HandlePick(MapInfo?, IReadOnlyList<DynamicPickHit>?)with a default parameter — existing call sites that pass onlyMapInfokeep compiling.Resources/Strings.resx+Strings.cs; tooltip on the dynamic-section header.Design doc
docs/design/dynamic-source-pick.mdanswers Q1–Q6 (sibling DTO type, 12px tolerance, separate pick service, sectioned single-list UI, all-resx strings, selection ring deferred). Linked fromdocs/toc.ymland the viewer README's new Picking dynamic features subsection.Out of scope (noted in design doc)
Verification
dotnet build -c Releaseclean (0 errors; 2 pre-existing warnings).dotnet test -c Releasegreen across every suite (2,388 passed, 2 skipped).DynamicSourceHitTesterTests— tolerance hit/miss, ordering by distance, multi-source walk, empty-coordinate skip, invalid-resolution guard.DynamicSourcePickServiceTests— empty registry, full attribute projection (Position / COG / Heading / SOG / MMSI / Name / Call sign), display-label fallback to feature id.PickReportViewModelTests— dynamic-onlySetPicksflipsHasPick, mixed dataset+dynamic preserves selection,Clear()clears dynamic, both-empty resets state.