@@ -55,17 +55,24 @@ ScatterplotPlugin::ScatterplotPlugin(const PluginFactory* factory) :
5555
5656 shortcuts.add ({ QKeySequence (Qt::Key_R), " Selection" , " Rectangle (default)" });
5757 shortcuts.add ({ QKeySequence (Qt::Key_L), " Selection" , " Lasso" });
58+ shortcuts.add ({ QKeySequence (Qt::Key_P), " Selection" , " Polygon" });
5859 shortcuts.add ({ QKeySequence (Qt::Key_B), " Selection" , " Circular brush (mouse wheel adjusts the radius)" });
5960 shortcuts.add ({ QKeySequence (Qt::SHIFT), " Selection" , " Add to selection" });
6061 shortcuts.add ({ QKeySequence (Qt::CTRL), " Selection" , " Remove from selection" });
62+ shortcuts.add ({ QKeySequence (Qt::Key_A), " Selection" , " Select all" });
63+ shortcuts.add ({ QKeySequence (Qt::Key_E), " Selection" , " Clear selection" });
64+ shortcuts.add ({ QKeySequence (Qt::Key_I), " Selection" , " Invert selection" });
6165
6266 shortcuts.add ({ QKeySequence (Qt::Key_S), " Render" , " Scatter mode (default)" });
6367 shortcuts.add ({ QKeySequence (Qt::Key_D), " Render" , " Density mode" });
6468 shortcuts.add ({ QKeySequence (Qt::Key_C), " Render" , " Contour mode" });
6569
70+ shortcuts.add ({ QKeySequence (Qt::Key_Plus), " Navigation" , " Zoom in by 10%" });
71+ shortcuts.add ({ QKeySequence (Qt::Key_Minus), " Navigation" , " Zoom out by 10%" });
6672 shortcuts.add ({ QKeySequence (Qt::ALT), " Navigation" , " Pan (LMB down)" });
6773 shortcuts.add ({ QKeySequence (Qt::ALT), " Navigation" , " Zoom (mouse wheel)" });
6874 shortcuts.add ({ QKeySequence (Qt::Key_O), " Navigation" , " Original view" });
75+ shortcuts.add ({ QKeySequence (Qt::Key_B), " Navigation" , " Zoom to selection" });
6976
7077 _dropWidget = new DropWidget (_scatterPlotWidget);
7178
@@ -257,8 +264,11 @@ void ScatterplotPlugin::init()
257264
258265 renderersNavigationGroupAction->setShowLabels (false );
259266
260- renderersNavigationGroupAction->addAction (const_cast <NavigationAction*>(&_scatterPlotWidget->getPointRenderer ().getNavigator ().getNavigationAction ()));
261- renderersNavigationGroupAction->addAction (const_cast <NavigationAction*>(&_scatterPlotWidget->getDensityRenderer ().getNavigator ().getNavigationAction ()));
267+ renderersNavigationGroupAction->addAction (const_cast <NavigationAction*>(&_scatterPlotWidget->getPointRendererNavigator ().getNavigationAction ()));
268+ renderersNavigationGroupAction->addAction (const_cast <NavigationAction*>(&_scatterPlotWidget->getDensityRendererNavigator ().getNavigationAction ()));
269+
270+ _scatterPlotWidget->getPointRendererNavigator ().getNavigationAction ().setParent (&_settingsAction);
271+ _scatterPlotWidget->getDensityRendererNavigator ().getNavigationAction ().setParent (&_settingsAction);
262272
263273 navigationLayout->addWidget (renderersNavigationGroupAction->createWidget (&getWidget ()));
264274 }
@@ -295,6 +305,11 @@ void ScatterplotPlugin::init()
295305
296306 getLearningCenterAction ().getViewPluginOverlayWidget ()->setTargetWidget (_scatterPlotWidget);
297307
308+ connect (&getScatterplotWidget ().getPointRendererNavigator ().getNavigationAction ().getZoomSelectionAction (), &TriggerAction::triggered, this , [this ]() -> void {
309+ if (_selectionBoundaries.isValid ())
310+ _scatterPlotWidget->getPointRendererNavigator ().setZoomRectangleWorld (_selectionBoundaries);
311+ });
312+
298313#ifdef VIEW_SAMPLING_HTML
299314 getSamplerAction ().setHtmlViewGeneratorFunction ([this ](const ViewPluginSamplerAction::SampleContext& toolTipContext) -> QString {
300315 QStringList localPointIndices, globalPointIndices;
@@ -400,27 +415,43 @@ void ScatterplotPlugin::selectPoints()
400415 const auto zoomRectangleWorld = navigator.getZoomRectangleWorld ();
401416 const auto screenRectangle = QRect (QPoint (), pointRenderer.getRenderSize ());
402417
418+ float boundaries[4 ]{
419+ std::numeric_limits<float >::max (),
420+ std::numeric_limits<float >::lowest (),
421+ std::numeric_limits<float >::max (),
422+ std::numeric_limits<float >::lowest ()
423+ };
424+
403425 // Go over all points in the dataset to see if they are selected
404426 for (std::uint32_t localPointIndex = 0 ; localPointIndex < _positions.size (); localPointIndex++) {
405-
406- // Compute the offset of the point in the world space
407- const auto pointOffsetWorld = QPointF (_positions[localPointIndex].x - zoomRectangleWorld.left (), _positions[localPointIndex].y - zoomRectangleWorld.top ());
427+ const auto & point = _positions[localPointIndex];
408428
409- // Normalize it
410- const auto pointOffsetWorldNormalized = QPointF (pointOffsetWorld. x () / zoomRectangleWorld.width (), pointOffsetWorld. y () / zoomRectangleWorld.height ());
429+ // Compute the offset of the point in the world space
430+ const auto pointOffsetWorld = QPointF (point. x - zoomRectangleWorld.left (), point. y - zoomRectangleWorld.top ());
411431
412- // Convert it to screen space
413- const auto pointOffsetScreen = QPoint (pointOffsetWorldNormalized .x () * screenRectangle .width (), screenRectangle. height () - pointOffsetWorldNormalized. y () * screenRectangle .height ());
432+ // Normalize it
433+ const auto pointOffsetWorldNormalized = QPointF (pointOffsetWorld .x () / zoomRectangleWorld .width (), pointOffsetWorld. y () / zoomRectangleWorld .height ());
414434
415- // Continue to next point if the point is outside the screen
416- if (!screenRectangle.contains (pointOffsetScreen))
417- continue ;
435+ // Convert it to screen space
436+ const auto pointOffsetScreen = QPoint (pointOffsetWorldNormalized.x () * screenRectangle.width (), screenRectangle.height () - pointOffsetWorldNormalized.y () * screenRectangle.height ());
418437
419- // If the corresponding pixel is not transparent, add the point to the selection
420- if (selectionAreaImage.pixelColor (pointOffsetScreen).alpha () > 0 )
421- targetSelectionIndices.push_back (localGlobalIndices[localPointIndex]);
438+ // Continue to next point if the point is outside the screen
439+ if (!screenRectangle.contains (pointOffsetScreen))
440+ continue ;
441+
442+ // If the corresponding pixel is not transparent, add the point to the selection
443+ if (selectionAreaImage.pixelColor (pointOffsetScreen).alpha () > 0 ) {
444+ targetSelectionIndices.push_back (localGlobalIndices[localPointIndex]);
445+
446+ boundaries[0 ] = std::min (boundaries[0 ], point.x );
447+ boundaries[1 ] = std::max (boundaries[1 ], point.x );
448+ boundaries[2 ] = std::min (boundaries[2 ], point.y );
449+ boundaries[3 ] = std::max (boundaries[3 ], point.y );
450+ }
422451 }
423452
453+ _selectionBoundaries = QRectF (boundaries[0 ], boundaries[2 ], boundaries[1 ] - boundaries[0 ], boundaries[3 ] - boundaries[2 ]);
454+
424455 switch (const auto selectionModifier = pixelSelectionTool.isAborted () ? PixelSelectionModifierType::Subtract : pixelSelectionTool.getModifier ())
425456 {
426457 case PixelSelectionModifierType::Replace:
@@ -467,7 +498,9 @@ void ScatterplotPlugin::selectPoints()
467498 }
468499 }
469500
470- _scatterPlotWidget->getPointRendererNavigator ().getNavigationAction ().getZoomSelectionAction ().setEnabled (!targetSelectionIndices.empty ());
501+ auto & navigationAction = _scatterPlotWidget->getPointRendererNavigator ().getNavigationAction ();
502+
503+ navigationAction.getZoomSelectionAction ().setEnabled (!targetSelectionIndices.empty () && !navigationAction.getFreezeNavigation ().isChecked ());
471504
472505 _positionDataset->setSelectionIndices (targetSelectionIndices);
473506
0 commit comments