views:

148

answers:

4

Otherwise known as a hard edge, this is a line over which the mouse cannot cross. Useful in games and the like.

Currently, I have a function that returns if my mouse cursor is in a polygon drawn on the screen. If it is not, I move my cursor to the last stored point that was in the polygon.

    if (!PointInPolygon(local, polyGon))
    {
        Cursor.Position = safePoint;
    }
    else
    {
        safePoint = Cursor.Position;
    }

I don't like this for a couple reasons:

  • Due to slow update times or for whatever reason, I am sometimes able to break out of the box. This then stores that position as the safePoint, outside of the polygon. My mouse is then stuck in this position.

  • Sloped edges should pust the mouse in the slope direction. Pushing the mouse right againts an "/" shaped wall should end up with the cursor in the top right corner. But due to the nature of this approach, going over the line will reset the cursor to where it previously was. Continuing to push right will only keep reseting the cursor, and will not push it "up the slope."

Are there any other approaches to tackle this problem? I'm mainly worried about the last issue: this slope transversal behavior is the main objective of my program and I need to get it working. Even if I use this basic method, any ideas for an optimization of that specific behavior?


EDIT:

It has been suggested by Reed that I instead return to the point that is CLOSEST to the current out-of-bounds point. Given the 4 corner points of a quadrilateral, how would I find the closest point in/on the shape?

+2  A: 

Instead of tracking a "safePoint", I would do the following:

If you find your outside of your polygon, instead of reverting to a last known safe point, put the mouse to the closest point on/in the polygon to the current mouse location. This will help the feel, as well, since the cursor will tend to (slowly) follow slopes on the edge of polygons, etc.

It also eliminates the need to save the state between calls (safepoint).

Reed Copsey
Hmm, great idea. Now I only need to figure out, given the 4 points that bound the quadrilateral, what would be the best/easiest way to find the closest point?
cksubs
Here's some algorithms for you: http://www.devmaster.net/forums/archive/index.php/t-103.html With small polygons (depends on your situation, but usually less than 10 segments or so), just brute force searching point->segments is often the fastest approach.
Reed Copsey
A: 

Closest point:

if(mouse.x > maxX) 
    mouse.x = maxX;
else if(mouse.x < minX)
    mouse.x = minX;

// same for Y.
Eugene
It is a polygon boundary, not a rectangle -1
Ed Swangren
lol, serves me right for not looking the word up :)
Eugene
Well, then just drop normal to each side, and find shortest distanse between point and intersection of normal and the side.
Eugene
well, I suppose that a rectangle is a polygon, but I assume that the logic will need to handle *any* polygon.
Ed Swangren
+2  A: 

How to constrain point P inside a convex polygon (non-convex is a bit harder) in 2-D (assume clockwise winding order):

For each edge (Pi, Pj) of the polygon...

Find the normal vector N of the edge (unit vector pointing from Pi to Pj, rotated 90 degrees)

Find the displacement D from the edge to point P along N ( D = (P - Pi) dot N )

If D is positive (or negative for counter-clockwise winding order), then P = P - N*D

End loop :)

Evan Rogers
A: 
  1. Find the equation of the edge line using the two endpoints.
  2. -(1/slope) gives the slope of the perpendicular line.
  3. Solve for line equation of perpendicular line using the known point across the edge (location of the true mouse)
  4. Solve for intersection of edge line and perpendicular line.
  5. Put the fake cursor at that location.
cksubs