I have a square that rotates to a random angle and then travels in a straight line in the direction it is pointing. It does this by using a variable as its x axis and then calling
Variable++
Each frame.
unfortunatley i cannot work out how to return the exact position of the square because the square can be travelling at any angle and therefore doesn't rigidly follow the world coordinte grid. This means that the x variable is not the shapes x coordinate.
How do i return the shapes exact coordinates and how do i do it in such a way that i can have two squares drawn from the same class behaving differently.
So you've got a measure of distance from where the object started along its internal sideways axis and a measure of the angle between that axis and the horizontal?
If so then the formula you want is simple trigonometry. Assuming the object started at (x, y) and has travelled 'distance' units along an axis at an angle of 'angle' with the horizontal then the current position (x', y') is:
x' = x + distance * cos(angle)
y' = y + distance * sin(angle)
If you have the origin in the lower left of the screen and axes arranged graph paper style with x increasing to the right and y increasing as you go upward, that assumes that the angle is measured anticlockwise and that the object is heading along positive x when angle is zero.
If you'll permit a hand waving explanation, the formula works because one definition of sine and cosine is that they're the (x, y) coordinates of the point on the outside of a unit circle at the angle specified. It also matches with the very first thing most people learn about trigonometry, that sine is 'opposite over hypotenuse', and cosine is 'adjacent over hypotenuse'. In this case your hypotenuse has length 'distance' and and you want to get the 'opposite' and 'adjacent' lengths of a right angled triangle that coincides with the axes.
Assuming Android follows J2SE in this area, the one thing to watch out for is that Math.sin and Math.cos take an angle in radians, whereas OpenGL's rotatef takes an argument in degrees. Math.toDegrees and Math.toRadians can do the conversion for you.
When you made the shape you should have already specified its X & Y coordinates. Im not too sure what you mean when you say you cant find the coordinates?
Also make sure you do fame independent movement; currently you are adding one to your variable on every loop of your program. This means if it runs a 60 Frame Per Second(FPS) it will move 60 units, but if it runs at 30FPS it will move at half the speed
Related
Right now I am using this code as custom layout in android studio. But the large problem is that when pinch-to-zoom, it will zoom into the point 0,0 ,instead of zooming into the finger point.
https://gist.github.com/anorth/9845602
EDIT: Forked the original gist and updated it, view it here. It was a little more complex than I thought. The default pivot point for scaling a view is the center of the view. In order to make this work I had to set the view pivot to (0,0) and the adjust the translation for the pivot from the user's gesture.
I noticed in your onScale() override you are calling scaleDetector.getScaleFactor() but you are not calling scaleDetector.getFocusX() and scaleDetector.getFocusy(). These methods tell you what the focal point of the pinch-zoom is. You will have to call these methods and get this focal point (x,y) then do some calculations to figure out the translation required to keep that focal point. You will have to work this into your dx and dy values so that the translation accounts for the focal point.
To calculate the translation, you would take the focal point and multiply the x and y values by the change in scale factor. This tells you how far the point would move given focal point (0,0). So you would subtract x(updated) from x(original) and y(updated) from y(original) to get that move vector. Your translation values are the negated vector values. So:
scale(delta) = scaleDector.getScaleFactor() -- just the change, not the new scale factor
translation x = x(focal) - x(focal) * scale(delta)
translation y = y(focal) - y(focal) * scale(delta)
So obviously you would add these values to your dx and dy values for translation.
I want to rotate the whole value of a 3d vector into one axis using quaternion rotations.
The reason behind is that I want to align the X and Y Axis of my smartphone with the X and Y Axis of my vehicle in order to detect lateral and longitudinal acceleration separated on these two axis. Therefore I want to detect the first straight acceleration of the car and rotate the whole acceleration value into the heading axis (X-Axis) of the phone assuming a straight forward motion.
How do I achieve this?
I got it myself while this Link helped me a lot.
In the end I just needed to define the destination axis as a Vector V(Magnitude_Source, 0, 0), calculate the angle between V and the source vector and rotate the source vector.
I will have an oval in the plane.The x and y co-ordinates of the center of oval and radius of the oval is known.Using a particle to move around the plane,have to verify whether the oval is circled(by moving the particle through all the sides of the oval).
How can I verify whether the oval is circled by the particle?
Consider centre of oval is (0, 0deg) in polar coordinates.
I am assuming your particle doesn't go inside the boundary of oval(from your words side of oval).
Minimize min and max with start position(atan(yParticle-yOvalCentre, xParticle-xOvalCentre)) of particles. Everytime particles goes towards min update min angle and similar for max. Once max - min > 360, you have completed the circle.
When you decided to start painting oval around circle, you created the starting vector from circle center to point (let's call it mouse point).
(mouseX-circleX, mouseY-circleY) = start vector
So, initial angle between current and starting vector will be 0 (until you move your mouse).
Mohit suggested you to check whether your current vector achieved some delta (359 deg is enough) between minimal and maximal angle value (angle can vary between -180 .. 180).
I'm not sure about his formula, though. I think it's better to find angle between starting vector (ax,ay) and current (bx,by) using the fact that
[a,b] = |a|*|b|*sin(alpha) = ax*by - ay*bx
(a,b) = |a|*|b|*cos(alpha) = ax*bx + ay*by
atan( [a,b] / (a,b) ) = atan(tan(alpha)) = alpha
So, calculate current angle on every mouse move and update min/max values, until max-min < 359
If you want to check it simultaneously for several circles, do it simultaneously for array of starting vectors and min/max values)
UPD I've noted big problem here, after painting 180 degrees around circle you'll achive -180 point immediately. So I think the best thing to do is to accumulate some summary value of signed delta angles between current and prevous "MouseMove" callback. So, when summary value will become 359 or -359 that mean you maked valid clock or counter-clockwise rotation.
I have a custom drawn rectangle which i want to move in a circular path based on touch events.
It follows the direction of the touch for clockwise or anticlockwise movement but basically move in circular motion, as if moving on the edge of the circle.
My current thought process is as follows:
Based on the users current and previous x,y i shall find the angle in degrees and then move this rectangle by the same angle by re-drawing in the new position, just making sure that it moves on the edge of a circle.
But this leads to some confusion on the following:
1. how do i decide whether angle movement is clockwise or anti-clockwise.
2. I am not being able to figure out the math for this properly.
Would this be the best approach or is there a better idea for doing this?
Also, if this is the best approach, could someone please tell me the formula for calculating the angle by which i should move it while taking care of the clocking and anticlockwise ?
could someone please help?
please let me know if any more details are required.
Thanks
Steps
Here are a few steps in order to move your rectangle along a circle's rim when the user taps and holds to the side of the circle:
1. Obtain direction desired.
2. Obtain angle from current x and y coordinates.
3. Add direction (+1 if counterclockwise, -1 if clockwise) to angle.
4. Calculate new x and y coordinates.
5. Update/display rectangle.
Details
1. In pseudocode, direction = sign(Rectangle1.x - UsersFingerPosition.x). Here sign is a function returning -1 if the number was negative, 0 if it is 0, and 1 if it is positive. Note that sign(0) will only result when the user is on the exact x and y of your rectangle's location. In that case, the rectangle would not move (which should be good). In Java, the sign function is Math.signum().
2. To obtain the current angle use the following java code:
double angle = Math.toDegrees(Math.atan2(Circle.y-Rectangle1.y, Rectangle1.x-Circle.x));
Note the order of Circle.y-Rectangle.y and Rectangle.x...Circle.x. This is a result of the coordinate (0, 0) being in the top left corner instead of the center of the screen.
3. Simple enough, just add direction to angle. If desired, do something like
angle += direction*2; //So it will move more quickly
4. To get the new x and y coordinates of your rectangle, use the trigonometric functions sine and cosine:
Rectangle1.x = Math.cos(Math.toRadians(angle))*Circle.radius + Circle.x - Rectangle1.width;
Rectangle1.y = Math.sin(Math.toRadians(angle))*Circle.radius + Circle.y - Rectangle1.height;
(where Circle.x and Circle.y are the coordinates of the center of your circle and Circle.radius is naturally it's radius).
5. This one you'll have to take care of (or have already) :)!
Hope this helps you!
Steps
Here are a few steps in order to move your rectangle along a circle's rim:
1. Obtain finger position/Check that it's still dragging the rectangle.
2. Obtain angle from current x and y coordinates.
3. Calculate new x and y coordinates.
4. Update/display rectangle.
Details
1. This one is probably specific to your code, however, make sure that when the user starts dragging the rectangle, you set a variable like rectangleDragging to true. Before you run the next steps (in the code), check that rectangleDragging == true. Set it to false once the user lets go.
2. To obtain the current angle use the following java code:
double angle = Math.toDegrees(Math.atan2(Circle.y-Finger.y, Finger.x-Circle.x));
Note the order of Circle.y-Finger.y and Finger.x...Circle.x. This is a result of the coordinate (0, 0) being in the top left corner instead of the center of the screen.
3. To get the new x and y coordinates of your rectangle, use the trigonometric functions sine and cosine:
Rectangle1.x = Math.cos(Math.toRadians(angle))*Circle.radius + Circle.x - Rectangle1.width;
Rectangle1.y = Math.sin(Math.toRadians(angle))*Circle.radius + Circle.y - Rectangle1.height;
(where Circle.x and Circle.y are the coordinates of the center of your circle and Circle.radius is naturally it's radius). Subtracting the width and height of the rectangle should center it on the circle's border instead of placing the left, upper corner on the circle.
4. This one you'll have to take care of (or have already) :)!
Hope this helps you!
If you have a "ball" inside a 2D polygon, made up of say, 4 line segments that act as bounding walls, how do you calculate the angle of the ball after the collision with the irregularly sloped wall?
I know how to make the ball bounce if the wall is horizontal, vertical, or at a 45 degree angle. I also have my code setup to detect a collision with the wall.
I've read about dot products and normals, but I cannot figure out how to implement these in Java / Android. I'm completely stumped and feel like I've looked up everything 10 pages deep in Google 10 times now. I'm burned out trying to figure this out, I hope someone can help.
Apologies in advance: I don't know the correct Android types. I'm assuming you have a vector type with properties 'x' and 'y'.
If the wall were horizontal and the current velocity were 'vector' then it'd be as easy as:
vector.y = -vector.y;
And you'd leave the x component alone. So you need to do something analogous, but more general.
You do that by substituting the idea of the line normal (a vector perpendicular to the line) for hard coding for the y axis (which is perpendicular to the horizontal).
Since the normal is orthogonal to the line, it can be found by rotating the line by 90 degrees. In 2d, the vector (a, b) can be rotated by 90 degrees by converting it to (-b, a). Hence if you have a line from (x1, y1) to (x2, y2) then you can get the normal with:
vectorAlongLine.x = x2 - x1;
vectorAlongLine.y = y2 - y1;
normal.x = -vectorAlongLine.y;
normal.y = vectorAlongLine.x;
You don't actually care how long the original line was (and it'll affect computations later when you don't want it to), so you want to make the normal be of length 1 irrespective of its current length. You can do that by dividing it by its current length. So, e.g.
lengthOfNormal = Math.sqrt(normal.x*normal.x + normal.y*normal.y);
normal.x /= lengthOfNormal;
normal.y /= lengthOfNormal;
Using the Pythagorean theorem there to get the length.
With the horizontal line, flipping on the y axis was the same as (i) working out what the extent of the vector extends along the y axis; and (ii) subtracting that amount twice — once to get the velocity to be 0 in that direction, again to make it the negative version of the original. That is, it's the same as:
distanceAlongNormal = vector.y;
vector.y -= 2.0 * distanceAlongNormal;
The dot product is used in the general case is to work how far the vector extends along the normal. So it does the same as taking vector.y does for the horizontal line. This is where you possibly have to take a bit of a leap of faith. It's a property of the dot product and you can persuade yourself by inspecting a right-angled triangle. But for now, if you had a horizontal line, you'd have ended up with the normal (0, 1). Since the dot product would be:
vector.x * normal.x + vector.y * normal.y
You'd compute:
distanceAlongNormal = vector.x * 0.0 + vector.y * 1.0;
Which is obviously the same thing as just taking the y component.
Having worked out the distance along the normal, you actually want to then subtract that amount times the normal times two. The only additional step here is multiplying by the normal to get a 2d quantity to subtract. That's because you're looking to subtract in the order of the normal. So complete code, based on a normal computed earlier, is:
distanceAlongNormal = vector.x * normal.x + vector.y * normal.y;
vector.x -= 2.0 * distanceAlongNormal * normal.x;
vector.y -= 2.0 * distanceAlongNormal * normal.y;
If you hadn't made normal of length 1, then you'd need to divide by the length here, since the dot product would scale the distanceAlongNormal value by that amount.
This might come in handy for you
http://www.tonypa.pri.ee/vectors/tut07.html