- Home /
Math Help - snapping to points
Ok, I can't seem to visualize the solution to this:
If you have 4 points in a rectangle shape, with these coordinates:
0,0......4,0
0,4......4,4
if you want a point somewhere in this rectangle to "snap" to then corners of this rectangle, you divide the x coordinate by 4, round it, multiply by 4. Do the same with the Y coordinate.
Now...what about this situation:
........2,0......
0,2..............4,2
........2,4......
Instead of needing the coordinates for the corners to snap to, I need to snap to the center of the rectangle sides. The center of the rectangle is NOT a valid point.
I can't seem to figure out the math to do this. I could probably do some lengthy if statements... (if X is here and Y is here, it's on this side) type stuff, but it seems like there would be a more elegant solution. Right now, my brain just can't seem to picture it. Any help on this?
[Edit] I realize I could easily get the midpoints of the 4 sides, and figure out which one the arbitrary point in square is closest to. Since snapping to the corners is as simple as this:
snapX = Round(originalx /4)*4
snapY = Round(originalY /4)*4
I was hoping for something similar, that didn't require more complex logic. Don't know if that is possible though :)
Answer by WillTAtl · Nov 04, 2011 at 07:01 PM
This is not really a unity question in any sense, but I'll answer it anyway, 'cause I'm in a good mood :)
not gonna be able to do this without some logic I don't think, though not sure I would call it COMPLEX logic in any case.
Convert the pos to one relative to the cube center, i.e....
centeredTouch = touchPos - boxCenterPos;
then compare the absolute x and y values, picking the larger one (furthest from center == closest to edge). That'll tell you if you're snapping to up/down or to left/right. Then for each case, decide which direction to snap based on the sign of that component's value.
if (abs(centeredTouch.x)>abs(centeredTouch.y))
{
if (centeredTouch.x<=0)
snapPos=leftSnapPos;
else
snapPos=rightSnapPos;
}
else
{
if (centeredTouch.y<=0)
snapPos=upSnapPos;
else
snapPos=downSnapPos;
}
this'll snap to whichever edge of the box you're closest to in a straight line, which will work out to the same as which center you're closest to. If you want to specifically ignore the center, you'll have to add logic for that; in this pseudocode the tie would go to y if x/y are same distance, and up if up/down distances are the same, so a dead center touch would snap to up, and touches directly on the diagonals of the square would snap to up/down.
There may be a pure-math approach that has no conditional logic, but it's probably going to be more computationally expensive than this.
Actually...I don't think this quite gives me what I need. It only snaps me which quadrant (upper left, upper right, lower right, lower left). But if I just pick random points in the lower right quadrant, how can it know which side (the right or bottom side) I mean? I would need a test, if I picked above the diagonal, choose the right side, if I picked below the diagonal, I choose the lower side.
https://docs.google.com/drawings/d/1LxCtVA9WJDbROTHftU4lGDO3mruWJfmvk2NLN8chB3Q/edit?hl=en_US
That should illustrate my problem. I guess if you could "rotate" everything, it might be simple to find out. I've got something working now, that just finds the center points and then figures out which is closest to your mouse selection. I was just hoping for something less wordy :)
Read my explanation and logic again, it does not snap to corners, but to centers, and I assure you the logic is correct :) Add numbers to your diagram and go through the math and logic by hand if you don't believe me.
A rotation-based approach might be $$anonymous$$utely shorter, in terms of number of lines of code, but it's going to be far, far more expensive, computationally.
All the diagonal magic happens in this one line:
if (abs(centeredTouch.x)>abs(centeredTouch.y))
The absolute values of the x and the y coordinate will be exactly the same if your point is ON ANY DIAGONAL line. This means the diagonals are the borders between the 4 areas. Because of the abs() you can't tell if it's up or down and the same for left and right. That's why you need the two second ifs.
Your answer
Follow this Question
Related Questions
Initiate RayCast From Center of Camera? 2 Answers
Making a simple grid 2 Answers
Center of spherecast 0 Answers
How to find distance from center of object to the lowest point of object 3 Answers
Question regarding Rect center 0 Answers