question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Highlight point near cursor with pixel space awareness

See original GitHub issue

Hi,

I have an issue that visually it appears that the mouse is closer to a point but is highlighting another point because of the way the calculation is made and doesn’t take into account the axis scale. Looking into the method HighlightPointNearest the formula is only looking at the actual coordinates of the points (x1 - x) * (x1 - x) + (y1 - y) * (y1 - y) and not looking how the points are drawn on the screen.

Note how visually the mouse appears closure to (2, 200) point image

As I move the mouse vertically the highlighted point eventually moves from (1, 100) to (2, 200) image

Is there way to factor in the pixel location or the scale of the X and Y axis when different so that the point is highlighting correctly?

Sample Project

MainWindow.xaml.cs

/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
    ScottPlot.PlottableScatterHighlight sphTest;
    PlottableVLine vLine;
    PlottableHLine hLine;

    public MainWindow()
    {
        InitializeComponent();

        double[] xs = new double[] { 1, 2 };
        double[] ys = new double[] { 100, 200 };

        sphTest = pltTest.plt.PlotScatterHighlight(xs, ys, lineWidth: 0, color: System.Drawing.Color.Blue, markerSize: 10);

        vLine = pltTest.plt.PlotVLine(1, color: System.Drawing.Color.Red, lineStyle: LineStyle.Dash);
        hLine = pltTest.plt.PlotHLine(100, color: System.Drawing.Color.Red, lineStyle: LineStyle.Dash);

        pltTest.Render();
    }

    private void pltTest_MouseMove(object sender, MouseEventArgs e)
    {

        (double mouseX, double mouseY) = pltTest.GetMouseCoordinates();
        sphTest.HighlightClear();

        var (x, y, index) = sphTest.HighlightPointNearest(mouseX, mouseY);


        int pixelX = (int)e.MouseDevice.GetPosition(pltTest).X;
        int pixelY = (int)e.MouseDevice.GetPosition(pltTest).Y;

        (double coordinateX, double coordinateY) = pltTest.GetMouseCoordinates();

        XPixelLabel.Content = $"{pixelX:0.000}";
        YPixelLabel.Content = $"{pixelY:0.000}";

        XCoordinateLabel.Content = $"{coordinateX:0.00000000}";
        YCoordinateLabel.Content = $"{coordinateY:0.00000000}";

        vLine.position = coordinateX;
        hLine.position = coordinateY;

        pltTest.Render(skipIfCurrentlyRendering: true);
    }
}

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:10 (7 by maintainers)

github_iconTop GitHub Comments

1reaction
oszymczakcommented, Jan 28, 2021

@swharden thanks for the solution… tested it on my data set works perfect.

0reactions
swhardencommented, Jan 28, 2021

Hi @olofszymczak, @StendProg, and @bclehmann, this is an interesting discussion! There’s a lot to unpack here, and there are multiple ways to solve this problem. I think I found an efficient working solution to the primary issue. A few different topics are addressed here, so I’ll mention them separately:

Pixel-Aware GetPointNearest()

I’m still working on the PR, but briefly I modified the code that measures distance between two points so it now optionally incorporates the ratio of scales (pixels per unit) of X and Y axes. See #722 for details.

// Use it like this
double xyRatio = formsPlot1.Plot.XAxis.Dims.PxPerUnit / formsPlot1.Plot.YAxis.Dims.PxPerUnit;
(double x, double y, int index) = MyScatterPlot.GetPointNearest(mouseCoordX, mouseCoordY, xyRatio);
// This is how it works
public (double x, double y, int index) GetPointNearest(double x, double y, double xyRatio = 1)
{
    double pointDistanceSquared(double x1, double y1) =>
        (x1 - x) * (x1 - x) * (xyRatio * xyRatio) + (y1 - y) * (y1 - y);

    /* rest of the function is unchanged */
}

Full code is here: ScatterPlot.cs#L324-L351

I’ll work to make this simpler, better-documented, and add a working demo. For now though, this seems to work.

Optimization may be improved

As discussed above, it may be possible to further optimize this method for speed. I haven’t benchmarked it, but if LINQ and tuples are replaced with discrete statements it may run faster. This is outside the scope of the original issue, but worth considering. I added it as a low-priority triaged task in #716 and I probably won’t do it soon, but if someone wants to do this and make a PR I’d be happy to take a look.

ScatterPlotHighlight is Deprecated in ScottPlot 4.1

This plot type was useful for a while, but it has a highly undesirable design: it mixes point distance detection with rendering. This design limits what the user can do. For example, the user could not use this plot type to render something different (like an arrow) as a highlight. Also this plot type cannot be used for Signal plots or other plot types.

In ScottPlot 4.1 a IHasPoints interface was created that has a few GetPointNearest() methods. Plottables where highlight functionality is desired can simply implement this interface. Since it does not control rendering, users can display the highlight however they want.

The recommended way to display a highlighted point is to use AddPoint() to place a point (a scatter plot with a single X/Y value), set its marker shape to filled circle, then set its color and size how you like. When the mouse moves you can find the point nearest the mouse, then change this point’s X/Y position and visibility, and request a render. This method is demonstrated verbosely in this WinForms app: Form1.cs

scales

Read more comments on GitHub >

github_iconTop Results From Across the Web

Mouse Position - ScottPlot FAQ
Highlight the Data Point Near the Cursor. Since it is easy to determine which data point is nearest the cursor, it is possible...
Read more >
Cursor location and pixel value in a Jupyter notebook ...
I would like to be able to move my cursor over an image and know it's location and pixel value An example could...
Read more >
How to add a highlighter to your mouse pointer in Windows ...
Near the bottom of this screen you will see a checkbox labeled Show Location of Pointer When I Press the CTRL key. Check...
Read more >
How to keep track of your mouse pointer with the ...
Another tool highlights every mouse click you make. The third tool will help you move your mouse pointer long distances across the screen....
Read more >
15 Animated Cursor Effects & Ideas for Your Website [+ ...
Check out some of the coolest animated cursor effects used on real websites, and learn how to create your own.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found