Skip to content

Commit 3c74056

Browse files
committed
BVV: fix marker hotkey reliability and fly-to bookmark drift
Fix two bugs in the BVV viewer: 1. The 'M' hotkey for placing markers would silently stop working mid-session. Now we register SNT shortcuts through BDV's nputActionBindings instead, which seems way more reliable. 2. Double-clicking a bookmark to fly to its position caused progressive drift on repeated clicks, and flew to the wrong location entirely for non-axis-aligned source transforms. The old code multiplied world coordinates by diagonal matrix elements only, ignoring rotation. Now computes the full affine mapping and sets the translation to centre the bookmark on screen.
1 parent bac9e5a commit 3c74056

2 files changed

Lines changed: 33 additions & 14 deletions

File tree

‎src/main/java/sc/fiji/snt/BookmarkManager.java‎

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -419,7 +419,7 @@ private JPopupMenu importMenu() {
419419
menu.add(jmi);
420420
jmi.addActionListener(e -> {
421421
final File file = (sntui != null) ? sntui.openFile("csv")
422-
: guiUtils.getFile(null, "csv");
422+
: guiUtils.getFile(new File(SNTPrefs.lastKnownDir(), "Markers.csv"), "csv");
423423
if (file != null) {
424424
recordCmd("load(\"" + file.getAbsolutePath() + "\")");
425425
loadBookmarksFromFile(file);
@@ -521,7 +521,7 @@ private void saveToUserChosenFile(final File file) {
521521
if (noBookmarksError()) return;
522522
final File saveFile = (file != null) ? file
523523
: (sntui != null) ? sntui.saveFile("Export Bookmarks to CSV...", "SNT_Bookmarks.csv", "csv")
524-
: guiUtils.getSaveFile("Export Markers to CSV...", null, "csv");
524+
: guiUtils.getSaveFile("Export Markers to CSV...", new File(SNTPrefs.lastKnownDir(), "Markers.csv"), "csv");
525525
if (saveFile != null) {
526526
recordCmd("save(\"" + saveFile.getAbsolutePath() + "\")");
527527
if (saveBookMarksToFile(saveFile)) {
@@ -704,11 +704,23 @@ private void flyTo(final int row) {
704704
final Bookmark b = model.getDataList().get(table.convertRowIndexToModel(row));
705705
final net.imglib2.realtransform.AffineTransform3D current = new net.imglib2.realtransform.AffineTransform3D();
706706
bvv.getViewerPanel().state().getViewerTransform(current);
707-
// Build a target transform that centres on the bookmark world position
707+
// The viewer transform maps world -> screen. To centre the bookmark on
708+
// screen we keep the current rotation/scale but adjust the translation
709+
// so that the bookmark's world position maps to the screen centre.
710+
// screenPos = R * worldPos + t, so t_new = screenCentre - R * worldPos
711+
final double[] worldPos = {b.getX(), b.getY(), b.getZ()};
712+
final double[] mapped = new double[3];
713+
current.apply(worldPos, mapped);
714+
// mapped = R * worldPos + t_current, so R * worldPos = mapped - t_current
715+
final double rx = mapped[0] - current.get(0, 3);
716+
final double ry = mapped[1] - current.get(1, 3);
717+
final double rz = mapped[2] - current.get(2, 3);
718+
final double cX = bvv.getViewerPanel().getWidth() / 2.0;
719+
final double cY = bvv.getViewerPanel().getHeight() / 2.0;
708720
final net.imglib2.realtransform.AffineTransform3D target = current.copy();
709-
target.set(target.get(0, 3) - b.getX() * current.get(0, 0), 0, 3);
710-
target.set(target.get(1, 3) - b.getY() * current.get(1, 1), 1, 3);
711-
target.set(target.get(2, 3) - b.getZ() * current.get(2, 2), 2, 3);
721+
target.set(cX - rx, 0, 3);
722+
target.set(cY - ry, 1, 3);
723+
target.set( - rz, 2, 3);
712724
bvv.getViewerPanel().setTransformAnimator(
713725
new bdv.viewer.animate.SimilarityTransformAnimator(current, target, 0, 0, 300));
714726
bvv.getViewer().getViewer().showMessage(String.format("Flying to %s", b.label));

‎src/main/java/sc/fiji/snt/viewer/Bvv.java‎

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1129,13 +1129,19 @@ private void attachControlPanel(final BvvSource source) {
11291129
bvvFrame.getCardPanel().addCard("Scene Controls", sceneControlsPanel, true);
11301130
// SNT toolbar
11311131
bvvFrame.getCardPanel().addCard("SNT Annotations", sntToolbar(actions), true);
1132-
// Register shortcuts: M key to place a marker at the current mouse position; shift+S for screenshot()
1133-
final InputMap iMap = bvvFrame.getViewerPanel().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
1134-
final ActionMap aMap = bvvFrame.getViewerPanel().getActionMap();
1135-
iMap.put(KeyStroke.getKeyStroke('m'), "snt-add-marker");
1136-
aMap.put("snt-add-marker", actions.addMarkerAction());
1137-
iMap.put(KeyStroke.getKeyStroke('S'), "snt-bvv-snapshot");
1138-
aMap.put("snt-bvv-snapshot", snapshotAction());
1132+
// Register shortcuts through BDV's keybindings system so they are
1133+
// handled at the same level as BVV's own shortcuts (e.g., Shift+B).
1134+
// Using Swing's InputMap/ActionMap directly gets shadowed by BDV's
1135+
// input trigger layer.
1136+
final InputMap sntIMap = new InputMap();
1137+
final ActionMap sntAMap = new ActionMap();
1138+
sntIMap.put(KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_M, 0), "snt-add-marker");
1139+
sntAMap.put("snt-add-marker", actions.addMarkerAction());
1140+
sntIMap.put(KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_S,
1141+
java.awt.event.InputEvent.SHIFT_DOWN_MASK), "snt-bvv-snapshot");
1142+
sntAMap.put("snt-bvv-snapshot", snapshotAction());
1143+
bvvFrame.getKeybindings().addInputMap("snt", sntIMap);
1144+
bvvFrame.getKeybindings().addActionMap("snt", sntAMap);
11391145
SwingUtilities.invokeLater(bvv::expandAndFocusCardPanel);
11401146
// Ensure the card panel is wide enough to show all controls without clipping.
11411147
// Use the Scene Controls panel's own preferred width since it's the widest,
@@ -2636,7 +2642,8 @@ private JToolBar buildIconToolbar(final BvvActions bvvActions) {
26362642
bvvInstance.repaint();
26372643
}
26382644
}),
2639-
"Show/hide coordinate axes at the volume origin",
2645+
"Show/hide coordinate axes at the volume origin.\n" +
2646+
"X: Red; Y: Green; Z: Blue",
26402647
IconFactory.GLYPH.CHART_LINE, IconFactory.GLYPH.CHART_LINE);
26412648
axesToggle.setSelected(false);
26422649
bar.add(axesToggle);

0 commit comments

Comments
 (0)