What is the opposite of the Math.tan(double x) function of java?
I know that Tan(X) = oppositeSideLength/AdjacentSideLength
but I have the opposite and adjacent sides so I want to do the opposite operation.
ie: x = Tan^-1(oppositeSideLenght/AdjacentSideLength) (that is how I would enter it in a calculator.
I just looked in the Math class and I know that there is:
Math.atan(
Math.atan2
but I don't think that either of these is what I am looking for.
Yes, you do indeed want atan, or sometimes, atan2. The difference between the two is that atan will fail under some circumstances when one of the side lengths are zero. While that may be unlikely for triangles, it is a possibility for some other, more general uses of atan. In addition, the atan function gives you an angle limited to the interval [-pi/2,pi/2]. So if you think about the atan function as a function of two inputs, (x,y), atan(y/x) will yield the same result as atan((-y)/(-x)). This is a serious flaw in some circumstances.
To solve these problems, the atan2 is defined such that it yields the correct result for all values of x and y, in any quadrant. One would use it as
atan2(oppositesidelength,adjacentsidelength)
to yield a consistent result.
Of course, for use in a non-degenerate triangle, the simple call to atan(opposite/adjacent) should be entirely adequate for your purposes.
Yep, you want atan, the arc tangent. This is the inverse of tangent; same thing with sin and arc sine, cosine and arc cosine, etc. These are alternative mathematical terminology for these functions' inverses.
Notice how atan returns angles from -π/2 to π/2, by the way. That's a hint that it's an inverse function (tangent takes angles and spits out ratios, arc tangent takes ratios and spits out angles). It is also important to recognize the restricted range. You won't necessarily get back your original angle, since tangents repeat every π radians (every 180°) — tan(π) = 0, but atan(0) = 0, not π.
Math.atan and Math.atan2 should work just fine.
angle = Math.atan(Math.Tan(radians));
angle = Math.atan(oppositeSideLength/adjacentSideLength)
angle = Math.atan2(oppositeSideLength, adjacentSideLength)
Math.atan is indeed the opposite of tangent. It's called arctangent.
Basically x = arctan(tan(x)). Well, it's a tad more complex than that seeing that tangent is a repetitive function (it needs some adjustments by adding k*pi). You should check out the wikipedia article about the details.
Anyway, you can indeed compute x (the angle) by doing Math.atan(opposite/adjacent). Take note though that the angle will be in radians, so make sure you convert to other units if that's not what your using.
Related
I'm making a simple 2d Java game similar to goemetry wars. I'm currently programming the player's shooting.
I have a target point specified by the mouse location. Now I want to add a bit of randomization, so that the shooting angle has a random offset. I am currently converting the point to a vector directly. My idea was to convert the vector to an angle, apply the randomization to that angle, and then, convert the angle back to a vector (given the length of the vector).
I can't figure out how to convert the angle back to a vector. I don't need code, it's basically just a question about the maths.
If there's a better way to randomize the shooting, I would love to hear that too! I can!t apply the randomization to the point because there are other things then the mouse that can set it.
Polar coordinate system
As everybody seems to have just answered in the comments, here goes the answer to your question as it is formulated : you need to use the polar coordinate system.
Let's call your angle a, the angle you want to add to it b, so the modified angle is a+b.
In the polar coordinate system, your point is represented by an angle a = Math.atan2(y, x) and a radius r = sqrt(x*x + y*y). If you just use the angle, you loose some information, which is at which distance the mouse is from your (0,0) point.
Converting back from your polar representation (after the angle has been modified) is now possible : x = r * Math.cos(a+b), y = r * Math.sin(a+b)
Without computing the angle
By using some cool trigonometry formulas, we can do better. We don't need to go to an angle and come back to a vector, we can modify the x and y values of the vector directly, still changing the angle like you want.
Remember that we want to find x'=r cos(a+b) and y'=r sin(a+b). We will obviously the following formulas :
Now let us multiply by r on both sides to get what whe want.
We now recognize x=r cos(a) and y=r sin(a), so we have the final expression :
If you come to think of it, for small values of b (which is what you want), sin(b) is close to 0, and cos(b) is close to 1, so the perturbation is small.
Not only do you reduce the number of trigonometry operations from 3 to 2, but you also have a cos and a sin of small values, which is nice if they are computed from Taylor series, makes convergence very fast. But that's implementation dependent.
NB: An alternative (and more elegant?) way to find the same result (and exact same formulas) is to use a rotation matrix.
I can haz cod
Whoopsie, you said you didn't want code. Well let's do it like this : I don't post it here, but if you want to compare with how I'd do it once you're done coding your implementation, you can see mine in action here : http://ideone.com/zRV4lL
I am making a simple Asteroids-like game using Java that involves angles, but I'm not sure how I should format the angles and directions of the various objects.
I have three main questions:
Where should 0 radians be? (Should it be pointing upwards, should it point to the right, etc.)
Should turning clockwise increase or decrease the value?
Should the range of the value be from 0 to (2 * pi) or from -pi to pi?
In general, you should always follow the same conventions concerning angles in ANY language, as angles are really more mathematical than computer-related concepts and math is universal (e.g. the angle-related math functions in any reasonable language should, and in my experience do behave the same way).
Therefore, these conventions are not so much unique to java as they are a good set of rules to follow whenever you're dealing with angles:
0 radians is to the right.
increasing the angle means moving counterclockwise, so pi/2 radians is up, pi is left, ect.
The last one is a bit trickier. Mathematically speaking, the range of angles around the unit circle is [0, 2pi], and this how I prefer to use angles. In general, this makes things easier, but some java functions seem to utilize the other approach. The main trigonometric functions sin, cos, and tan can accept any number as a input (for instance sin(pi) == sin(3pi)), just as the domain of these functions in mathematics is All Real Numbers. The range of these functions does not relate to pi. However, the inverse trigonometric functions (asin, acos, and atan, but NOT atan2) have limited ranges that are defined in the javadoc:
the returned angle is in the range -pi/2 through pi/2.
Which is also consistent with mathematics. Therefore:
Most of time, you should use [0, 2pi]. It's easier to read and easier to operate on.
When dealing with the inverse trigonometric functions, keep in mind that their range is [pi/2, -pi/2] and make conversions as necessary.
UPDATE: Thanks Kevin, I meant <= in the title, not <.
Is this correct? It's the best I've managed after an embarrassing amount of time on the problem:
public int candidate_answer(double f, float g) {
int test = (int)Math.floor(f / g);
if ((test + 1) * g <= f) {
test++;
}
return test;
}
Background:
The application is a simple game that I've taken over ownership for from a previous programmer. Curiously, he has chosen to mix floats and doubles wantonly, both in member and argument variables, so there's a lot of unnecessary implicit and explicit casting going up and down.
The player coordinates are at double x, y (the player is assumed to be a point). There is a float TILE_SIZE, and the world is some number of rows and columns worth of tiles, plus some generic out-of-bounds handling. Assuming the (x,y) coordinate is in bounds, I'm trying to figure out which tile the user is in, based on x (to get column) or y (to get row). This is like, programmer 101.
WLOG, At first I was just doing col = (int)(x/TILE_SIZE). But as I discovered, e.g., .5/.1f < 5, and thus (int)(.5/.1f) == 4, the wrong answer. This led to the above if statement and formulation of the problem.
Then I discovered that, e.g., (int)(-9.999999747378752E-5 / .1f) == 0, which led me to call Math.floor first.
But now I'm not sure what other bugs lurk in this approach, or what the best approach would be.
(It may not seem like such a big deal if the user is right on the cusp of being in one row or another, and we accidentally round to the wrong one; but the real issue is in the code, where we see unexpected sign changes (+, -, 0). For instance, some of the code assumes that if the user is on the tile at (r,c), then it's point is actually contained by that tile geometry. When it's not, we get things like negative distances when only non-negative are expected, and etc., and it causes asserts to fire and while loops to break and so on.)
I think you should try to fix the root problem (.1f too far away from .1), i.e. turn TILE_SIZE into a double, or use floats consistently everywhere. Otherwise you might get similar problems caused by minimal rounding errors throughout the code. The candidate_answer function is a hack to work around a problem that should not exist in the first place.
P.S.
For this particular problem, you might just want to find a formula that is more robust, i.e. isn't sensitive to minimal rounding errors in one direction only. Try to put the player in the center of its field instead of at the tile edge where it can easily fall into rounding errors:
col = (int)((x + MINIMAL_STEP_SIZE / 2.0) / TILE_SIZE)
(Ideally, the MINIMAL_STEP_SIZE/2 part would already be part of x instead of being added here)
Using double's all the way seems to be the way to go. However, this does not solve the root problem: Using floating point arithmetic is always bound to rounding errors.
When using floating point arithmetic, it is always good to work with an Epsilon (e) of accuracy:
If you want to check if x is equal to y (where one variable is a floating point type), use the following pattern:
if(x-y < e){
...
}
Epsilon must be defined (globally or at your opinion for a certain domain) based upon your requirements. For example:
e = 0.00001d;
If f and g are both positive (they seem to be), your method may be reduced to a single, simple calculation:
public static int candidate_answer(double f, float g) {
return (int)(g/f);
}
This is correct because if
i*f <= g
then by dividing both sides by f yields
i <= g/f
Casting to int automatically gives you "the largest int less than or equal to the result" because when casting all non-integer parts are discarded - it's like executing a floor() call.
If f or g are allowed to be negative, this approach would still work, but dealing with the sign would have to be added (not much code, but I doubt it is required given they way the question is worded.
If I have an object with properties of x an y, how can I tell which point in an array is the closest without using the distance formula?
You can't get an accurate result without using some variant of the distance formula. But you can save a few cycles by not taking the square root after the fact; the comparison will remain valid.
r = dx2 + dy2
If you don't care about the exact distance, you could perhaps take the difference between the x and y coordinates of your source and destination points to provide you with some ordering.
//The following code does not return the closest point,
//but it somewhat does what you need and complies with
//your requirement to not use the distance formula
//it finds the sum of x and y displacements
Point destination=...
Point nearestPoint= points.get(0);
for (Point p : points){
closenessCoefficient= Math.abs(destination.x-p.x) + Math.abs(a.destination-p.y);
nearestPoint=Math.Min(closenessCoefficient, nearestPoint);
}
return nearestPoint;
If you have to find exactly the closest neighbour, there is no way around evaluating the distance formula, at least for a couple of points. As already pointed out, you can avoid evaluating the expensive sqrt for most of the time when simply comparing the distance-squared r^2 = x^2 + y^2.
However, if you have a big number of points spread out over a large range of distances, you can first use an approximation like the ones shown here http://www.flipcode.com/archives/Fast_Approximate_Distance_Functions.shtml . Then you can calculate the real distance formula only for the points closest as given by the approximation. On architectures where also the multiplication is expensive, this can make a big difference. On modern x86/x86-64 architectures this should not matter much though.
I am looking for an open source package (preferably Java but R or other languages would be ok too) that provides these 2 functions
1) points output_seq[] SCALE(points input_seq[], double factor)
In other words a sequence of doubles (x1,y1), (x2,y2)... is given as input that represents a graph (each point is connected to the next by a straight line) and a scaling factor is given. Then it returns a similar sequence as output. The catch is that the output sequence may have fewer or more elements than the input. For example, if I request magnification by a factor of 2.012 then the output sequence may have twice as many elements as the input. The scaling factor should be a double, not an integer.
Lastly, it's important to return the output sequence as points (doubles), I have very little interest in the actual drawing on a screen beyond proving that it does the right thing.
2) points output_seq[] ROTATE(points input_seq[], double angle)
same as above, except there is no scaling but just rotation, the angle is from 0 to 359.9999 and is given in radians.
The size of the output is always the same as the size of the input.
Again the emphasis is on getting the output sequence as doubles, not so much on the actual drawing on a screen.
If you know the right terminology I should have used then let me know.
Thank you so much.
In Java, Path2D is suitable for 2D floating point coordinates. The lineTo() method will add straight lines to the path. Because Path2D implements the Shape interface, rotate and scale are possible via createTransformedShape(). One approach to interpolation, using PathIterator, is shown here.