0

I have a bunch of coordinates and I draw them as a coordinate system on a bitmap image. While hovering my mouse over my image, I want to highlight the coordinates that are within certain Distance from my MousePosition using the below routine:

public void HighLightNearbyDots(Point _mousePosition)
{
    // ..

    foreach (var point in myDisplayedCoords)
    {
        Distance = (int)(MousePosition - point); // this gets the distance between two points and converts it to an int

        if (Distance < 10)
            point.Color = Colors.Red;
        else
            point.Color = InitialCoordColor;
    }
    DrawImage();
}

Now, if I find a Nearby coordinates, I want to Change my CursorShape to be a HAND. I can not do that inside if (Distance < NearbyCursorDistance); Why? Because I will either need to change back to Arrow (which takes a micro second) on the else and user won't see it, or it will stay as HAND for the rest of execution. So I implement this:

private bool IsThereANearbyDot(CoordPoint _mousePosition)
{
    foreach(var point in MyDisplayedCoords)
    {
        if (10 > (int) (_mousePosition - point))
            return true;
    }
    return false;
}

And use it this way:

public void HighLightNearbyDots(Point _mousePosition)
{
    //..

    if (IsThereANearbyDot(MousePosition))
        CursorShape = Cursors.Hand;
    else
        CursorShape = Cursors.Arrow;

    foreach (var point in myDisplayedCoords)
    {
        Distance = (int)(MousePosition - point); 

        if (Distance < 10)
            point.Color = Colors.Red;
        else
            point.Color = InitialCoordColor;
    }
    DrawImage();
}

It works but if MyDisplayedCoords is huge, which I have to iterate twice now, it takes a lot of time and users will notice lagging on the screen. How could I solve this problem?

Khalil Khalaf
  • 9,259
  • 11
  • 62
  • 104
  • What's the definition for `myDisplayedCoords`? – Visual Vincent Jul 18 '16 at 20:31
  • Hi again! It is a `List` and a`CoordPoint` is a simple point just `x` and `y` @VisualVincent – Khalil Khalaf Jul 18 '16 at 20:32
  • What are you targetting: Winforms, WPF, ASP..? __Always__ tag your question correctly! – TaW Jul 18 '16 at 20:34
  • 1
    @TaW Ops, sorry. It is a Wpf and I will add the tag – Khalil Khalaf Jul 18 '16 at 20:35
  • 1
    Perhaps you could perform some kind of binary search on the list? At least it would decrease the need of iterating _everything_. – Visual Vincent Jul 18 '16 at 21:07
  • @VisualVincent I think I will research that. And original loop is yes iterating _everything_ however the second just breaks on first match. So if I draw from left to right, my frame rates are faster when my mouse is on the left side – Khalil Khalaf Jul 18 '16 at 21:12
  • Binary search (simplified) works in the way that you sort a list, then you check the item (or items) in the middle of the list and determine if the target is in the first or second half of the list. Then you split that half in half and check the middle if the target is in the first or second half... this continues until you have found (or not found) what you were looking for. -- Or maybe [**this has some even better methods**](http://stackoverflow.com/questions/9113780/fast-algorithm-to-find-the-x-closest-points-to-a-given-point-on-a-plane). – Visual Vincent Jul 18 '16 at 21:19

1 Answers1

2

All you need to do is set the cursor to the default (arrow) at the start of your HighLightNearbyDots() method and then set to hand in the distance < 10 clause (and not the else). E.g.:

public void HighLightNearbyDots(Point _mousePosition)
{
    // ..

    CursorShape = Cursors.Arrow;

    foreach (var point in myDisplayedCoords)
    {
        Distance = (int)(MousePosition - point); // this gets the distance between two points and converts it to an int

        if (Distance < 10)
        {
            CursorShape = Cursors.Hand;
            point.Color = Colors.Red;
        }
        else
            point.Color = InitialCoordColor;
    }
    DrawImage();
}

You shouldn't have any problems with the cursor flickering, but if you do then you could set a flag and just set the cursor once in the method, like this:

public void HighLightNearbyDots(Point _mousePosition)
{
    // ..
    bool handCursor = false;

    foreach (var point in myDisplayedCoords)
    {
        Distance = (int)(MousePosition - point); // this gets the distance between two points and converts it to an int

        if (Distance < 10)
        {
            handCursor = true;
            point.Color = Colors.Red;
        }
        else
            point.Color = InitialCoordColor;
    }

    CursorShape = handCursor ? Cursors.Hand : Cursors.Arrow;
    DrawImage();
}

This will ensure that the cursor is resolved each time you execute the HighLightNearbyDots() method (which presumably you are doing periodically, e.g. on mouse-move events), and that it will be the default cursor unless you've highlighted any dots, in which case it will be the hand.

If that does not address your question, please provide a good Minimal, Complete, and Verifiable example that shows clearly what you're doing, along with a precise explanation of what the code does and what you want it to do instead, as well as what specifically you are having trouble figuring out.

Community
  • 1
  • 1
Peter Duniho
  • 68,759
  • 7
  • 102
  • 136
  • Hi Peter, thanks for this fix that addresses exactly exact situation, which is why I did not post additional unneeded information in my OP. I will try it and I think it makes sense and that it will work. How come I did not think of that! Upvoted too :) – Khalil Khalaf Jul 18 '16 at 22:39
  • 1
    _"How come I did not think of that"_ -- everything's obvious, once you've seen it. :) It can be hard to find the obvious when you're too close to the problem. Sometimes, all you need is another set of eyes on it. – Peter Duniho Jul 18 '16 at 23:49
  • Definitely :) My mind set was focused on details. I will do it as soon as I get to work tomorrow :) – Khalil Khalaf Jul 19 '16 at 01:26