Math help for parallelograms on canvas - math

First let me say that I'm not very good with math. I have a canvas with multiple text "boxes" that are rotated to 300°, which basically makes them parallelograms. They are very similar to this:
I'm trying to detect if the mouse is over one of them, but I don't know how to do that. Please help. Thank you!

The simplest method is to use the inverse transform on the mouse point and then do simple rectangle testing on the transformed point. As long as the affine transform you're using doesn't map everything to a line, it will have a well-defined inverse.

Each parallelogram can first of all be contained in a rectangular bounding box like the one illustrated above. If the mouse is not within that rectangle, then it is definitely not a hit. You have many easy tests for that already. The rest of the space can be decomposed into the parallelogram of interest in green, and the areas you don't want. So we just need to test if the mouse is in the red areas with the following tests:
Left: x < a - (a/h)*y
Right: x > (a+b) - (a/h)*y
If either of those conditions is true, then the mouse is outside the parallelogram.
Note, in this case I am assuming y is 0 at the top and increases as you move down, and x is zero at the left and increases as you move right.
For more information about the value of a, we can turn to trig.
If we know the angle theta and h, then
a = h tan(Ɵ)

Related

Centering Perspective Camera on two objects by panning

In Unity, I have a perspective camera, and I've got two transforms in my scene that I want the camera to perfectly center on screen. The camera will pan left/right/up/down to the appropriate location.
So far my approach has been to convert the transform positions to screen positions using Camera.WorldToScreenPoint, and taking their average to find the screen midpoint. From there, I know I want to pan the camera a certain number of units toward that midpoint. What I'm having trouble with is figuring out the formula for deciding how much to pan (or, maybe this isn't even the preferred way to determine this).
I think your approach is great. Let me expand the idea.
So this is your screen :D. Blue circle is where you want your objects to be. There are two scenarios. We will use green dots as an example of zooming scenario. Then red dots for panning scenario.
The trick is, you want to keep the dots as close as possible to circumference of blue circle.
Let's say you get red dots as your objects' screen position. You have to shift them towards the center. Let's calculate CenterOfDots. Then calculate it's difference to CenterOfBlueCircle. That's how much pan you need in screen coordinates.
So you have calculated the pan. Now you want to know how much you need to zoom. Let's say you get green dots this time. Calculate DistanceBetweenDots and compare it to DiameterOfBlueCircle. You want them to be the same. So their difference is how much zoom you need in screen coordinates.
There comes the tricky part. Now you know how much to pan and zoom in screen space. But you need to move the camera in world space. Trying to solve it using geometry magic is fine. But I hate headache :D
So instead, I would iteratively shift my camera using the data I calculated above. Just shift the camera in it's local x-y axes towards HowMuchPan, multiplied by a manually given coefficient PanSpeed. This will give a smooth transition to the camera. Same is for the zoom. This time you shift the camera in it's local z axis using HowMuchZoom multiplied by your manually given coefficient ZoomSpeed.
Hope it helps. Have fun :)
i figured out the mathy approach!
for panning, you want to figure out the average screen position of your objects (i.e. the middle). then you want to generate a couple world points against an arbitrary plane some distance away from the camera. the difference between these points is how much to pan the camera
center=Camera.ScreenToWorldPoint(Screen.width*0.5f, Screen.height*0.5f, 10f)
mid=Camera.ScreenToWorldPoint(averageScreenPoint.x, averageScreenPoint.y, 10f)
Camera.transform.Translate(mid-center)
zooming is a bit more complicated, but very similar to the panning approach. you want to use Camera.ScreenToWorldPoint against an arbitrary plane, but you want to do this for 4 points, which will help you figure out a scale to apply to your camera's z position. psuedocode -
screenMin = Camera.ScreenToWorldPoint(0f,0f,10f);
screenMax = Camera.ScreenToWorldPoint(Screen.width,Screen.height,10f);
objMin = Camera.ScreenToWorldPoint(screenPosMin.x, screenPosMin.y, 10f);
objMax = Camera.ScreenToWorldPoint(screenPosMax.x, screenPosMax.y, 10f);
screenDiff = screenMax-screenMin;
objDiff = objMax-objMin;
Vector3 scale = new Vector3(objDiff.x/screenDiff.x, objDiff.y/screenDiff.y, 0f);
ratio = scale.x < scale.y ? scale.y : scale.x;// pick the one that best puts fits on screen.
Camera.localPosition.z = Mathf.Min(ZoomMin, Camera.localPosition.z*ratio);

determine rectangle rotation point

I would like to know how to compute rotation components of a rectangle in space according to four given points in a projection plane.
Hard to depict in a single sentence, thus I explain my needs.
I have a 3D world viewed from a static camera (located in <0,0,0>).
I have a known rectangular shape (an picture, actually) That I want to place in that space.
I only can define points (up to four) in a spherical/rectangular referencial (camera looking at <0°,0°> (sph) or <0,0,1000> (rect)).
I considere the given polygon to be my rectangle shape rotated (rX,rY,rZ). 3 points are supposed to be enough, 4 points should be too constraintfull. I'm not sure for now.
I want to determine rX, rY and rZ, the rectangle rotation about its center.
--- My first attempt at solving this constrint problem was to fix the first point: given spherical coordinates, I "project" this point onto a camera-facing plane at z=1000. Quite easy, this give me a point.
Then, the second point is considered to be on the <0,0,0>- segment, which is about an infinity of solution ; but I fix this by knowing the width(w) and height(h) of my rectangle: I then get two solutions for my second point ; one is "in front" of the first point, and the other is "far away"... I now have a edge of my rectangle. Two, in fact.
And from there, I don't know what to do. If in the end I have my four points, I don't have a clue about how to calculate the rotation equivalency...
It's hard to be lost in Mathematics...
To get an idea of the goal of all this: I make photospheres and I want to "insert" in them images. For instance, I got on my photo a TV screen, and I want to place a picture in the screen. I know my screen size (or I can guess it), I know the size of the image I want to place in (actually, it has the same aspect ratio), and I know the four screen corner positions in my space (spherical or euclidian). My software allow my to place an image in the scene and to rotate it as I want. I can zoom it (to give the feeling of depth)... I then can do all this manually, but it is a long try-fail process and never exact. I would like then to be able to type in the screen corner positions, and get the final image place and rotation attributes in a click...
The question in pictures:
Images presenting steps of the problem
Note that on the page, I present actual images of my app. I mean I had to manually rotate and scale the picture to get it fits the screen but it is not a photoshop. The parameters found are:
Scale: 0.86362
rX = 18.9375
rY = -12.5875
rZ = -0.105881
center position: <-9.55, 18.76, 1000>
Note: Rotation is not enought to set the picture up: we need scale and translation. I assume the scale can be found once a first edge is fixed (first two points help determining two solutions as initial constraints, and because I then know edge length and picture width and height, I can deduce scale. But the software is kind and allow me to modify picture width and height: thus the constraint is just to be sure the four points are descripbing a rectangle in space, with is simple to check with vectors. Here, the problem seems to place the fourth point as a valid rectangle corner, and then deduce rotation from that rectangle. About translation, it is the center (diagonal cross) of the points once fixed.

How to detect if my mouse position is within a rectangle c#?

I am trying to write an application to draw schematic diagrams which contain rectangles, lines and circles. Now I want to add another functionality to drag a rectangle to different position. The problem I am facing is to detect whether I have clicked within a rectangle or not. I know there is a function like Rectangle.Contains(Point). To use such method I need to use a for loop to check against each rectangle. If I have a large number of rectangles present, then its not wise to use this method. Is there any other way to do this task.
You need a computer graphics textbook, this and similar problems are often discussed.
If memory serves me, make sure the point is below the top edge of the rectangle, above the bottom edge, left of the right edge and right of the left edge.
Regarding testing a bunch of rectangles in a loop. Consider having a circle that each rectangle fits in, a bounding circle. First test to see if the point is farther from the origin of the circle than the radius of the circle. If so there is no need to test the rectangle, its a miss. OK, that was a very theoretical answer. In reality calculating the distance from the point to the origin can be a very expensive calculation, it involves a square root, it may be faster to do the four comparisons of the point in rectangle check. Again if memory servers me, we don't really care what the distance from the origin is only if it is greater than the radius. So only partially perform the distance calculation, omitting the final square root, and compare against the square of the radius. Of course you still need to experiment and profile to make sure this bounding circle check is faster than just doing the regular point in rectangle check and you need to make sure you will have sufficient misses to offset the hits where you will end up doing both the bounding circle and rectangle checks.
You need to use a spatial index to find quickly in which rectangle the mouse is. I suggest a R-tree, here is the theorical part:
http://en.wikipedia.org/wiki/R-tree
And the c#,implementation:
http://sourceforge.net/projects/cspatialindexrt/
Create an rtee, add your rectangles then call the rtree.nearest method with the mouse coordinate to know the rectangles containing the mouse cursor. You can play with the distance parameter.
Hope it helps,
Anben Panglose.
I would go about dividing the display region into a quadrant.
Then place the rectangles into top-left, top-right, bottom-left, bottom-right grids.
Placing them means, creating a list for every quadrant and placing the rectangles in it.
Once the point is clicked, determine which quarter it belongs to and search in those rectangles only. This approach reduces your linear search by 4 times.
Remember that you need to also take care of overlapping where the point can belong to many rectangles. Here the z-order of your rectangles matter. So while the list is maintained for a quadrant, it should be sorted with it's z-order as a key.
Hope this helps.
May be something like this?
public bool isRectangelContainPoint(RectangleF rec, PointF pt)
{
if (pt.X >= rec.Left && pt.X <= rec.Right && pt.Y <= rec.Bottom && pt.Y >= rec.Top)
return true;
else
return false;
}

Math/Calculations for infinite/repeating world with rotation

How do I make a infinite/repeating world that handles rotation, just like in this game:
http://bloodfromastone.co.uk/retaliation.html
I have coded my rotating moving world by having a hierarchy like this:
Scene
- mainLayer (CCLayer)
- rotationLayer(CCNode)
- positionLayer(CCNode)
The rotationLayer and positionLayer have the same size (4000x4000 px right now).
I rotate the whole world by rotating the rotationLayer, and I move the whole world by moving the positionLayer, so that the player always stays centered on the device screen and it is the world that moves and rotates.
Now I would like to make it so that if the player reaches the bounds of the world (the world is moved so that the worlds bounds gets in to contact with the device screen bounds), then the world is "wrapped" to the opposite bounds so that the world is infinite. If the world did not rotate that would be easy, but now that it does I have no idea how to do this. I am a fool at math and in thinking mathematically, so I need some help here.
Now I do not think I need any cocos2d-iphone related help here. What I need is some way to calculate if my player is outside the bounds of the world, and then some way to calculate what new position I must give the world to wrap the world.
I think I have to calculate a radius for a circle that will be my foundry inside the square world, that no matter what angle the square world is in, will ensure that the visible rectangle (the screen) will always be inside the bounds of the world square. And then I need a way to calculate if the visible rectangle bounds are outside the bounds circle, and if so I need a way to calculate the new opposite position in the bounds circle to move the world to. So to illustrate I have added 5 images.
Visible rectangle well inside bounds circle inside a rotated square world:
Top of visible rectangle hitting bounds circle inside a rotated square world:
Rotated square world moved to opposite vertical position so that bottom of visible rectangle now hitting bounds circle inside rotated world:
Another example of top of visible rectangle hitting bounds circle inside a rotated square world to illustrate a different scenario:
And again rotated square world moved to opposite vertical position so that bottom of visible rectangle now hitting bounds circle inside rotated world:
Moving the positionLayer in a non-rotated situation is the math that I did figure out, as I said I can figure this one out as long as the world does not get rotate, but it does. The world/CCNode (positionLayer) that gets moved/positioned is inside a world/CCNode (rotationLayer) that gets rotated. The anchor point for the rotationLayer that rotates is on the center of screen always, but as the positionLayer that gets moved is inside the rotating rotationLayer it gets rotated around the rotationLayer's anchor point. And then I am lost... When I e.g. move the positionLayer down enough so that its top border hits the top of the screen I need to wrap that positionLayer as JohnPS describes but not so simple, I need it to wrap in a vector based on the rotation of the rotationLayer CCNode. This I do not know how to do.
Thank you
Søren
Like John said, the easiest thing to do is to build a torus world. Imagine that your ship is a point on the surface of the donut and it can only move on the surface. Say you are located at the point where the two circles (red and purple in the picture) intersect:
.
If you follow those circles you'll end up where you started. Also, notice that, no matter how you move on the surface, there is no way you're going to reach an "edge". The surface of the torus has no such thing, which is why it's useful to use as an infinite 2D world. The other reason it's useful is because the equations are quite simple. You specify where on the torus you are by two angles: the angle you travel from the "origin" on the purple circle to find the red circle and the angle you travel on the red circle to find the point you are interested in. Both those angles wrap at 360 degrees. Let's call the two angles theta and phi. They are your ship's coordinates in the world, and what you change when you change velocities, etc. You basically use them as your x and y, except you have to make sure to always use the modulus when you change them (your world will only be 360 degrees in each direction, it will then wrap around).
Suppose now that your ship is at coordinates (theta_ship,phi_ship) and has orientation gamma_ship. You want to draw a square window with the ship at its center and length/width equal to some percentage n of the whole world (say you only want to see a quarter of the world at a time, then you'd set n = sqrt(1/4) = 1/2 and have the length and width of the window set to n*2*pi = pi). To do this you need a function that takes a point represented in the screen coordinates (x and y) and spits out a point in the world coordinates (theta and phi). For example, if you asked it what part of the world corresponds to (0,0) it should return back the coordinates of the ship (theta_ship,phi_ship). If the orientation of the ship is zero (x and y will be aligned with theta and phi) then some coordinate (x_0,y_0) will correspond to (theta_ship+k*x_0, phi_ship+k*y_0), where k is some scaling factor related to how much of the world one can see in a screen and the boundaries on x and y. The rotation by gamma_ship introduces a little bit of trig, detailed in the function below. See the picture for exact definitions of the quantities.
!Blue is the screen coordinate system, red is the world coordinate system and the configuration variables (the things that describe where in the world the ship is). The object
represented in world coordinates is green.
The coordinate transformation function might look something like this:
# takes a screen coordinate and returns a world coordinate
function screen2world(x,y)
# this is the angle between the (x,y) vector and the center of the screen
alpha = atan2(x,y);
radius = sqrt(x^2 + y^2); # and the distance to the center of the screen
# this takes into account the rotation of the ship with respect to the torus coords
beta = alpha - pi/2 + gamma_ship;
# find the coordinates
theta = theta_ship + n*radius*cos(beta)/(2*pi);
phi = phi_ship + n*radius*sin(beta)/(2*pi));
# return the answer, making sure it is between 0 and 2pi
return (theta%(2*pi),phi%(2*pi))
and that's pretty much it, I think. The math is just some relatively easy trig, you should make a little drawing to convince yourself that it's right. Alternatively you can get the same answer in a somewhat more automated fashion by using rotations matrices and their bigger brother, rigid body transformations (the special Euclidian group SE(2)). For the latter, I suggest reading the first few chapters of Murray, Li, Sastry, which is free online.
If you want to do the opposite (go from world coordinates to screen coordinates) you'd have to do more or less the same thing, but in reverse:
beta = atan2(phi-phi_ship, theta-theta_ship);
radius = 2*pi*(theta-theta_ship)/(n*cos(beta));
alpha = beta + pi/2 - gamma_ship;
x = radius*cos(alpha);
y = radius*sin(alpha);
You need to define what you want "opposite bounds" to mean. For 2-dimensional examples see Fundamental polygon. There are 4 ways that you can map the sides of a square to the other sides, and you get a sphere, real projective plane, Klein bottle, or torus. The classic arcade game Asteroids actually has a torus playing surface.
The idea is you need glue each of your boundary points to some other boundary point that will make sense and be consistent.
If your world is truly 3-dimensional (not just 3-D on a 2-D surface map), then I think your task becomes considerably more difficult to determine how you want to glue your edges together--your edges are now surfaces embedded in the 3-D world.
Edit:
Say you have a 2-D map and want to wrap around like in Asteroids.
If the map is 1000x1000 units, x=0 is the left border of the map, x=999 the right border, and you are looking to the right and see 20 units ahead. Then at x=995 you want to see up to 1015, but this is off the right side of the map, so 1015 should become 15.
If you are at x=5 and look to the left 20 units, then you see x=-15 which you really want to be 985.
To get these numbers (always between 0 and 999) when you are looking past the border of your map you need to use the modulo operator.
new_x = x % 1000; // in many programming languages
When x is negative each programming language handles the result of x % 1000 differently. It can even be implementation defined. i.e. it will not always be positive (between 0 and 999), so using this would be safer:
new_x = (x + 1000) % 1000; // result 0 to 999, when x >= -1000
So every time you move or change view you need to recompute the coordinates of your position and coordinates of anything in your view. You apply this operation to get back a coordinate on the map for both x and y coordinates.
I'm new to Cocos2d, but I think I can give it a try on helping you with the geometry calculation issue, since, as you said, it's not a framework question.
I'd start off by setting the anchor point of every layer you're using in the visual center of them all.
Then let's agree on the assumption that the first part to touch the edge will always be a corner.
In case you just want to check IF it's inside the circle, just check if all the four edges are inside the circle.
In case you want to know which edge is touching the circumference of the circle, just check for the one that is the furthest from point x=0 y=0, since the anchor will be at the center.
If you have a reason for not putting the anchor in the middle, you can use the same logic, just as long as you include half of the width of each object on everything.

moving items in JPanel

I am working on a pong game and I am working on the mechanism to move the ball. If I add 1 to x the ball moves 1 pixel to the right, if i add 1 to y the ball moves 1 pixel to the bottom. What if I want to move the ball at a certain angle how can 1 calculate the coordinates.
Trying to work with angles will get a bit more complicated than you need to get. For this kind of animation you generally want to use floats to store your objects x and y coordinates and move it by applying x and y deltas (The floats will preserve the detail of the position which is lost to rounding when drawn on the screen). The deltas represent the speed your object is moving in each axis and can be negative or positive.
For each iteration of your animation, add xdelta to your x coordinate and add ydelta to your y coordinate. Round them off to position them on the screen.
When you hit the top or bottom border, you would swap the sign on your ydelta component and likewise for side borders.
You wouldn't want to keep the same x and y delta all the time so when the objects hits a paddle, modify the x or y delta a little bit to change up the angle.
you are looking for line drawing algorithms, something like Bresenham or DDA you can find some reasonable implementations here ofcourse instead of drawing a complete line you would move your ball along that line but the way of finding the set of lines to move on is the same.
You might find these resources helpful.
for something like Pong you should be investigating vector math, but if all you want is to know an angle all you really need is SOHCAHTOA.

Resources