Finding angle between two points in Java behaving strange - java

I have been looking for an answer for several hours now, and have turned up nothing. If this is a duplicate, I apologize but I have been unable to find a solution to my specific problem on StackOverflow.
I have a function that finds the angle between a point and the y-axis:
public static double getAngle(float x1,float y1) {
float y_x = 0;
float y_y = 1;
float p_x = x1;
float p_y = y1;
float theta = (float)Math.atan2((p_x-y_x),(p_y-y_y));
return (float)Math.toDegrees(theta)
}
Then when I call it, i get strange behavior:
getAngle(1,1); //returns 90.00000250447816
getAngle(5,5); //returns 51.34019265119512
getAngle(10,10); //returns 48.012787449847956
getAngle(100,100); //returns 45.287917631417216
getAngle(1000,1000); //returns 45.02866072599646
I know the answer is 45. It would appear the function `getAngle(x,x) is converging on 45 as the limit of x approaches infinity. The issue is I need this function to work for values between 0.01 and 10.0
Does anybody know why the function is behaving this way and how I can get the answer I am looking for?
P.S. I initially tried using the dot-product identity acos((ax*bx+ay*by)/|a||b|) and got a similar problem

You should simply use
float theta = (float) ((Math.PI/2) - Math.atan2(y1, x1));
The reason that your getAngle(x, x) approaches the correct angle when x approaches infinity is that you were effectively computing
Math.atan2(x, x-1)
which is equivalent to
Math.atan(x / (x-1))
and hence obviously approaches the correct
Math.atan(1)
when x approaches infinity.

It seems like your math is wrong. My approach would be to find the angle to the horizontal and do 90 minus that. For example:
double theta = Math.PI/2 - Math.atan2(y1,x1); //answer in radians
Why you are wrong is because you are subtracting the vectors from each one another so that you are getting the angle of a triangle defined by the new vector. By measuring it to the X axis and subtracting it from 90 it will be a lot easier :D

Related

Find the modo value

I have given a log value Y , i want to calculate the anti log of Y i.e
ans = (Math.pow(10,Y))%mod
where mod = 1e9+7 and the anti log of Y will always be integer i.e Y is calculate as follow Y= log(a) a is very large integer of range 10^100000
So for given Y i need to calculate ans ? How to do that considering the mod operation.
My Approach
double D = Y -(int)Y
long Pow = (long)Y
for(int i=1;i<=Pow;i++) ans = (ans*10)%mod;
ans = (ans*Math.pow(10,D))%mod
But it's not correct can someone suggest be efficient approach here ? BigDecimal can be useful there ?
For Example:
Y = 16.222122660468525
Using the straight forward method and rounding off i.e Math.log(10,Y) give me 1667718169966651 but using loops it's give me 16677181699666510. I am not using mod now just explaining that there is an error.
Here Y is small so direct method works and we can take mod easily. if Y is range of 10000 it will not work and overflow so we have to used mod.
I guess it's should work
double D = Y -(int)Y
long Pow = (long)Y
for(int i=1;i<=Pow;i++) ans = (ans*10)%mod;
ans = (ans*Math.pow(10,D))
ans = Math.round(ans)
ans%=mod
There is an error in your judgement here - the loop method is not at fault.
The value of a in your example has 17 integer digits. From this stackoverflow post, a double has ~16 significant digits of precision. Thus both the loop and direct calculations are in fact being limited by lack of precision.
(Just to confirm, using a high precision calculator, the value of a is 16677181699666650.8689546562984070600381634077.... Thus both of your values are incorrect - unless you copied them wrongly?)
Thus your loop method is not the problem; you just need a
higher-precision method to do the last step (calculating pow(10, frac(Y))).
As a side note, there is a more efficient way of doing the loop part - this post has more details.

Finding the distance between two points [Efficency]

Instead of typing it all out, here's a picture for you to see what I want. You know what they say, a picture is worth a thousand words.
What I have is p1, Θ, and d and speed, s of the projectile.
Speed:
From this I can deduce p2 using the equation p1.x * speed, p1.y * speed which are the co-ordenates for p2. From this I can calculate the distance using the equation |dx| + |dy|.
Distance
However, if I wasn't given speed, how would I be able to calculate the co-ordenates of p2 only using Θ, p1 and d?
Are there any other methods that would be the most efficent?
public double getDistanceTraveled() {
return Math.abs(x - oldX) + Math.abs(y - oldY);
} //use Manhattan aproach as it is more efficent than Euclidean
public double getSpeed() {
return getDistanceTraveled() / level.TICKS_PER_SECOND;
}
is what I am using at the moment. I realized that I had the variable time, so I was able to deduce p2 using this method:
d = |dx| + |dy|d = s / ts = t(|dx| + |dy|)
Not sure if this is that efficient though. Any suggestions to this problem, and just to repeat: I have the variables theta, p1, d and t and I have to find p2.
Efficency >>> Accuracy
If theta is the angle between line and y-axis.
Then you can calculate it with the following formulas.
Let P1 be the point (p1x, p1y). and P2 be the point (p2x, p2y)
p2x = p1x + d * sin(theta)
p2y = p1y + d * cos(theta)
If you use Math.sin(theta), then keep in mind that theta should be in radians. You can use Math.toRadian(degree) to get angle in radians.
You know what they say, a picture is worth a thousand words.
If you want efficiency, there's actually a much better approach than using the trig operations at all. Basically, since you already have d, the only thing you care about is the relative movement along x and y, which is defined by theta.
Knowing that, it's pretty trivial to just store unit vectors at whatever your required granularity is in a hashmap and multiply by d
After you've decided on your granularity, just pre-calculate a HashMap like so:
{0: [1, 0],
0.01: [0.99, 0.001], etc...
}
Then round the incoming number, see this question for details on making sure it matches your granularity. Then the calculation is just (in pseudo-code):
x = p1[0] + d * <HashMap>.getKey(angle)[0]
y = p2[1] + d * <HashMap>.getKey(angle)[1]
A HashMap lookup and a multiplication is WAY more efficient than even a single trig operation. Preliminary tests got me ~10x speedup but YMMV.

Java: Calc x in sin(x)

My question is about angle functions in programming languge Java. if i want to get sin of any double, i just use
double variable = Math.sin(x);
but what if sin(x) = 0.324 (or any other random number) and i want to calculate x? How can i do it? Are there any native function to this in java or i have to implement my own algorithm to return this value ?
getXForValue(0.324);
public double getXForValue(double val){
// how to calculate ?
return x;
}
Thanks.
What you are describing is known as the "arcsine" function. It's available in Java as Math.asin().
You may want to read the wiki on trigonometric functions.
Use the arcsin function
x = Math.asin(variable)
To calculate sine inverse in Java you can use
Math.asin(double a)
It returns the arc sine of a value; the returned angle is in the range -pi/2 through pi/2.. Check java docs for more explanation
You can use Math.asin(0.324); to get the value of x.
Please read the Math.asin() javadoc to be aware of what is returned by the function.
You have to use the inverse function or arcsine. It has the same relationship with sine as dividing has with multiplication.
5 * x = 10;
10 / 5 = x;
Math.sine(x) = 1;
Math.asine(1) = x;
you need to use the these Methods, Math.toDegrees and Math.asin, in the next order:
double x = 1.0; // in this example 1.0 corresp to sin(90)
double dX = Math.toDegrees(Math.asin(x));
System.out.println(dX);
Remember that the asin() function return a double RADIANS result.

Debug java function return point x distance along a line

public Point getPointOnSegment(double length, int x1, int y1, int x2, int y2) {
if(length==0) return new Point(x2, y2);
double angle = Math.atan((double)(y2-y1)/(double)(x2-x1));
return new Point((int)((length*Math.cos(angle))+x1), (int)((length*Math.sin(angle))+y1));
}
I have found this function that is supposed to return a point on a line that is x distance along said line. But for some reason it sometimes returns a point in the opposite direction that is is supposed to. It seems to happen if the angle of the line is greater than 180 degrees.
I have been looking at this for way over 5 hours now and I am afraid that I have stared myself blind to the issue. Can anyone see what the problem is, or suggest a better function to substitute it?
The issue is that you loose signs with your division. For example if both distances are negative the result will be positive as it would be for both beeing positive.
Try to calculate the angle using method atan2:
angle = Math.atan2((double)(y2-y1), (double)(x2-x1));
This function respects the signs of your differences in all cases and returns an angle for the complete clock. It also handles the special case for x2-x1 being zero.

Why is this bearing calculation so inacurate?

Is it even that inaccurate? I re-implented the whole thing with Apfloat arbitrary precision and it made no difference which I should have known to start with!!
public static double bearing(LatLng latLng1, LatLng latLng2) {
double deltaLong = toRadians(latLng2.longitude - latLng1.longitude);
double lat1 = toRadians(latLng1.latitude);
double lat2 = toRadians(latLng2.latitude);
double y = sin(deltaLong) * cos(lat2);
double x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(deltaLong);
double result = toDegrees(atan2(y, x));
return (result + 360.0) % 360.0;
}
#Test
public void testBearing() {
LatLng first = new LatLng(36.0, 174.0);
LatLng second = new LatLng(36.0, 175.0);
assertEquals(270.0, LatLng.bearing(second, first), 0.005);
assertEquals(90.0, LatLng.bearing(first, second), 0.005);
}
The first assertion in the test gives this:
java.lang.AssertionError:
expected:<270.0> but
was:<270.29389750911355>
0.29 seems to quite a long way off? Is this the formula i chose to implement?
If you've done what you seem to have done and done it correctly you have figured out the bearing of A from B along the shortest route from A to B which, on the surface of the spherical (ish) Earth is the arc of the great circle between A and B, NOT the arc of the line of latitude between A and B.
Mathematica's geodetic functions give the bearings, for your test positions, as 89.7061 and 270.294.
So, it looks as if (a) your calculation is correct but (b) your navigational skills need polishing up.
Are you sure this is due to numeric problems? I must admit, that I don't exactly know what you are trying to calculate, but when you dealing with angles on a sphere, small deviations from what you would expect in euclidian geometry.
java.lang.AssertionError: expected:<270.0> but was:<270.29389750911355>
This 0.29 absolute error represents a relative error of 0.1%. How is this "a long way off"?
Floats will give 7 significant digits; doubles are good for 16. Could be the trig functions or the degrees to radians conversion.
Formula looks right, if this source is to be believed.
If I plug your start and final values into that page, the result that they report is 089°42′22″. If I subtract your result from 360 and convert to degrees, minutes, and seconds your result is identical to theirs. Either you're both correct or you're both wrong.

Categories

Resources