problem with angles - java

Hi
this a part of my code :
I have a list which its size is three and I consider that 2 last items are in one line (p and q) I need to get the angle between the first item of this list and these two points (p,q)
private Point partition(List<Point> list, Point p, Point q) {
double x1 = p.getX();
double x2 = q.getX();
double y1 = p.getY();
double y2 = q.getY();
double pQ = Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
for (int i = 0; i < list.size()-2; i++) {
double pointX = list.get(i).getX();
double pointY = list.get(i).getY();
double pointQ = Math.sqrt((x2 - pointX) * (x2 - pointX) + (y2 - pointY) * (y2 - pointY));
double pointP = Math.sqrt((pointX - x1) * (pointX - x1) + (pointY - y1) * (pointY - y1));
double angle = Math.acos((pQ * pQ - pointP * pointP - pointQ * pointQ) /(- 2 * pointP * pointQ));
System.out.println(angle);
}
but instead of printing an angle for the first item it will print :(first item is not in the line of two last items).
1.6288442476732894
those points that print this result are :
[X :143.0 Y: 217.0, X :93.0 Y: 163.0, X :193.0 Y: 165.0]
please help me thanks.
EDITED : really it makes me confused .in such a way it will print this value ,sorry all !!!

Your arccos is bad, you need a parenthesis and a - :
arccos((pQ^2 - pointP^2 - pointQ^2)/(-2 * pointP * pointQ))
see How to calculate an angle from three points?

NaN is a special double value meaning "not a number". It is generated as a result of some "bad" calculations:
dividing 0 by 0
dividing infinity by infinity (any combination of positive and negative)
multiplying 0 by infinity, either positive and negative, and vice-versa
adding negative and positive infinity
subtracting negative from positive infinity, and vice-versa
the square root of a negative number
the logarithm of a negative number
the inverse sine or cosine of a number not between -1 and 1
any calculation involving one or more NaN values.
Check the result of the argument to the inverse cosine function (acos). I bet it is off the valid range.

Related

Accurate Circular Orbit Equation in java

public void move(){
double angle;
for(int i = 0; i < planets.size(); i++){
if(Math.abs(Math.sqrt(Math.pow(ship.locX - (planets.get(i).locX + planets.get(i).radi), 2) + Math.pow(ship.locY - (planets.get(i).locY + planets.get(i).radi), 2))) < planets.get(i).gravrange){
//Distance formula between spaceship and planets to determine whether the ship is within the influence of the planet.
angle = ((Math.atan2((planets.get(i).locX + planets.get(i).radi) - ship.locX, (planets.get(i).locY + planets.get(i).radi) - ship.locY)) / Math.PI) + 1;
//The problematic math equation.
Produces a double from 0 to 2, 0 being when ship.locY < planets.get(i).locY && ship.locX == (planets.get(i).locX - planets.get(i).radi). (when relative X = 0 and relative Y < 0.)
if(ship.locX > (planets.get(i).locX + planets.get(i).radi)){xm += Math.cos(angle) * planets.get(i).gravrate;}
else{xm -= Math.cos(angle) * planets.get(i).gravrate;}
if(ship.locY > (planets.get(i).locY + planets.get(i).radi)){ym += Math.sin(angle) * planets.get(i).gravrate;}
else{ym -= Math.sin(angle) * planets.get(i).gravrate;}
}
}
This uses the data to modify the X and Y velocities of the spacecraft.
This equation works for the majority of an orbit, but under certain circumstances has an issue in which the spacecraft undergoes a retrograde force, slowing it. Shortly afterward it begins to be repelled by the planetary body, which after a short period begins attracting it again. When the spacecraft reaches the original position at which this occurred, it begins to move in the opposite direction of its original orbit.
This continues to occur until the spacecraft begins a wavelike motion.
Is there a way to solve this, or am I simply using the wrong equation? I've been attempting to fix this for about two weeks now. I have no education in physics nor calculus at this point in time, so my understanding is limited.
Edit: The comments had questions about my math, so I'll attempt to answer them here. From what I know about atan2, it produces a number from -pi to pi. I divide by pi to produce a number from -1 to 1, then add 1 to produce 0 to 2. I then use this number as a radian measurement. My knowledge of radians (unit circle) is that a circle's radian measure is 0 to 2pi.
Edit 2: The following code has very different math but produces the desired results, save for issues of repelling rather than attracting when approaching the North and South 'poles' of the planet.
public void move(){
double angle;
double x1, x2, y1, y2;
for(int i = 0; i < planets.size(); i++){
x1 = ship.locX;
y1 = ship.locY;
x2 = planets.get(i).locX + planets.get(i).radi;
y2 = planets.get(i).locY + planets.get(i).radi;
if(Math.abs(Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2))) < planets.get(i).gravrange){
//Distance formula between spaceship and planets
angle = (y2 - y1)/(x2 - x1); //Gets slope of line between points.
if(angle > 0){
if(y1 > y2){
xm += Math.cos(angle) * planets.get(i).gravrate;
ym += Math.sin(angle) * planets.get(i).gravrate;
}else{
xm -= Math.cos(angle) * planets.get(i).gravrate;
ym -= Math.sin(angle) * planets.get(i).gravrate;
}
}
else{
if(y1 > y2){
xm -= Math.cos(angle) * planets.get(i).gravrate;
ym -= Math.sin(angle) * planets.get(i).gravrate;
}else{
xm += Math.cos(angle) * planets.get(i).gravrate;
ym += Math.sin(angle) * planets.get(i).gravrate;}
}
}
}
I wrote it up very quickly to see if using the slope of the line rather than that strange atan2 equation would help. Apparently it did. I also made the code a bit more readable in this section.
The following code fixed my issue. I was overcomplicating my math equations as I usually do. Took me three weeks of Googling, asking people with degrees in physics and mathematics, and reading Javadocs before I figured that one out. Turns out how atan2 works is simply different from how I thought it worked and I was improperly using it.
The solution was simplifying the atan2 equation beforehand and removing the unnecessary additions.
x1 = ship.locX;
y1 = ship.locY;
x2 = planets.get(i).locX + planets.get(i).radi;
y2 = planets.get(i).locY + planets.get(i).radi;
if(Math.abs(Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2))) < planets.get(i).gravrange){
//Distance formula between spaceship and planets
angle = Math.atan2((y2 - y1),(x2 - x1)); //Converts the difference to polar coordinates and returns theta.
xm -= Math.cos(angle) * planets.get(i).gravrate; //Converts theta to X/Y
ym -= Math.sin(angle) * planets.get(i).gravrate; //velocity values.
}

Finding whether a point is within a triangle

I have been on this for hours, attempting different methods looking at just about every question. Perhaps I have it completely wrong, but I feel that I have my math of it correct, but no matter what numbers I input, I get the same output. My code is off somewhere and I have to turn it in by midnight.
It is the all so fun: Find if a point is within a triangle code. (for beginners)
import java.util.Scanner;
public class PointsTriangle {
// checks if point entered is within the triangle
//given points of triangle are (0,0) (0,100) (200,0)
public static void main (String [] args) {
//obtain point (x,y) from user
System.out.print("Enter a point's x- and y-coordinates: ");
Scanner input = new Scanner(System.in);
double x = input.nextDouble();
double y = input.nextDouble();
//find area of triangle with given points
double ABC = ((0*(100-0 )+0*(0 -0)+200*(0-100))/2.0);
double PAB = ((x*(0 -100)+0*(100-y)+0 *(y- 0))/2.0);
double PBC = ((x*(100-0 )+0*(0 -y)+200*(y-100))/2.0);
double PAC = ((x*(0 -100)+0*(100-y)+200*(y- 0))/2.0);
boolean isInTriangle = PAB + PBC + PAC == ABC;
if (isInTriangle)
System.out.println("The point is in the triangle");
else
System.out.println("The point is not in the triangle");
}//end main
}//end PointsTriangle
You placed the wrong value order into your formula; therefore, the result is wrong. If the 3 vertices are as the following
A(x1, y1) B(x2, y2), C(x3, y3)
then the area is calculated as
double ABC = Math.abs (x1 * (y2 - y3) + x2 * (y3 - y1) + x3 * (y1 - y2)) / 2;
After that, you just replace each vertex with the input point, we will have the following triangles: PBC, APC, ABP.
Put everything together, we will have the correct one
int x1 = 0, y1 = 0;
int x2 = 0, y2 = 100;
int x3 = 200, y3 = 0;
// no need to divide by 2.0 here, since it is not necessary in the equation
double ABC = Math.abs (x1 * (y2 - y3) + x2 * (y3 - y1) + x3 * (y1 - y2));
double ABP = Math.abs (x1 * (y2 - y) + x2 * (y - y1) + x * (y1 - y2));
double APC = Math.abs (x1 * (y - y3) + x * (y3 - y1) + x3 * (y1 - y));
double PBC = Math.abs (x * (y2 - y3) + x2 * (y3 - y) + x3 * (y - y2));
boolean isInTriangle = ABP + APC + PBC == ABC;
If you draw a picture, you can see the point has to satisfy simple inequalities (below / above / to the right of certain lines). Whether "on the edge" is in or out I will leave up to you:
Y > 0 (above the X axis)
X > 0 (to the right of the Y axis)
X + 2* Y < 200 (below the hypotenuse)
Write an if statement around these three and you're done:
if( (y > 0) && (x > 0) && (x + 2*y < 200) )
System.out.println("The point is in the triangle");
else
System.out.println("The point is not in the triangle");

Java Game - moving an object in a straight line to another point

Here is what I have so far:
int vx = (playerx - x);
int vy = (playery - y);
double distance = Math.sqrt((vx * vx) + (vy * vy));
double doublex = ((vx / distance));
double doubley = ((vy / distance));
dx = (int) Math.floor(doublex + 0.5);
dy = (int) Math.floor(doubley + 0.5);
x += dx;
y += dy;
I just want x and y to move straight towards playerx and playery but it moves only at a slope of 0, 1, or undefined.
I suspect it because you x and y are int and you have moving such a short distance that you will only be (1, 1), (1, 0) or (0, 1).
You need to allow it to move further that 1, or use a type which more resolution. e.g. double.
BTW: Instead of using Math.floor I believe a better choice is
dx = (int) Math.round(doublex);
You are dividing horizontal distance and vertical distance by total distance, this will always result in a number between 1 and -1 so each time it moves it will move by either nothing or by 1 in a direction. I guess this is in pixels?
Each time the move happens you should keep track of the actual distance moved and the desired distance moved because, for example, you may be trying to move 0.4 along the y axes in every loop, and it will never move because that will always round down. So if in the second loop you know you should have moved by 0.8 in total, you can round up to one, and leave the desired set to -0.2 and keep looping.
A solution similar to Bresanham's Line Algorithm can be implemented. IE:
function line(x0, y0, x1, y1)
real deltax := x1 - x0
real deltay := y1 - y0
real deltaerr := abs(deltay / deltax) // Assume deltax != 0 (line is not vertical),
// note that this division needs to be done in a way that preserves the fractional part
real error := deltaerr - 0.5
int y := y0
for x from x0 to x1
plot(x,y)
error := error + deltaerr
if error ≥ 0.5 then
y := y + 1
error := error - 1.0
Source: Bresanham's Line Algoithm

How to get coordinates of a point in a coordinate system based on angle and distance

How to get coordinates of a point in a coordinate system when all I have is the origin coordinates (x, y) and the angle from the origin to the point and the distance from the origin to the point?
You use Math.cos, Math.sin like this:
pointX = x + distance * Math.cos(angle)
pointY = y + distance * Math.sin(angle)
Note about radians / degrees
Math.cos and Math.sin assumes the argument is given in radians (0…2π). If you have the angle in degrees (0…360), you would use Math.cos(Math.toRadians(angle)) for instance.
If r is the distance from origin and a is the angle (in radians) between x-axis and the point you can easily calculate the coordinates with a conversion from polar coordinates:
x = r*cos(a)
y = r*sin(a)
(this assumes that origin is placed at (0,0), otherwise you should add the displacement to the final result).
The inverse result is made by computing the modulo of the vector (since a distance + angle make a vector) and the arctangent, which can be calculated by using the atan2 funcion.
r = sqrt(x*2+y*2)
a = atan2(y,x)
If d is the distance and A is the angle, than the coordnates of the point will be
(x+d*Cos(A), y+ d*Sin(A))
px = x + r * cos(phi)
py = y + r * sin(phi)
where [px py] is the point you are searching for, [x y] is the "origin", r is the distance and phi is the angle to the target from the origin.
EDIT: http://en.wikipedia.org/wiki/Polar_coordinate_system This link which was helpfully posted by Bart Kiers could yield some background information.
Short answer
// math equations
pointX = distance * cos(angle) + x
pointY = distance * sin(angle) + y
// java code [angle in radian]
double pointX = distance * Math.cos(Math.toRadians(angle)) + x;
double pointY = distance * Math.sin(Math.toRadians(angle)) + y;
Detailed answer
As per below diagram
// finding pointX let's start by
cos(angle) = (pointX - x) / distance
distance * cos(angle) = (pointX - x)
(pointX - x) = distance * cos(angle)
pointX = distance * cos(angle) + x
// finding pointY let's start by
sin(angle) = (pointY - y) / distance
distance * sin(angle) = (pointY - y)
(pointY - y) = distance * sin(angle)
pointY = distance * sin(angle) + y

Why is this line intersection code not working?

I have the following code to determine the intersection of two 2D lines. It's not working and I'm not sure why; I've been copying code from multiple sources without much change.
The lines extend infinitely from a given midpoint. The "vector()" referenced in the below code is a 2D vector of magnitude 1.0 that indicates the direction in which the line extends (the line also extends in the negative direction, it's not a ray).
Earlier, I was using this method for determining the intersection: Intersection point of two lines (2 dimensions)
After that gave me wrong results, I went with the method on Wikipedia.
float x1 = line1.location().x();
float y1 = line1.location().y();
float x2 = x1 + line1.vector().x();
float y2 = y1 + line1.vector().y();
float x3 = line2.location().x();
float y3 = line2.location().y();
float x4 = x3 + line2.vector().x();
float y4 = y3 + line2.vector().y();
float d = ((x1 - x2) * (y3 - y4)) - ((y1 - y2) * (x3 - x4));
if(d == 0) // If parallel, defaults to the average location of the lines.
return new Vector2f((x1 + x3) * 0.5f, (y1 + y3) * 0.5f);
else
{
float a = (x1 * y2) - (y1 * x2);
float b = (x3 * y4) - (y3 * x4);
return new Vector2f(((a * (x3 - x4)) - ((x1 - x2) * b)) / d,
((a * (y3 - y4)) - ((y1 - y2) * b)) / d);
}
Two examples of how it is wrong (The orange dot is the returned point of intersection):q
It returns a point along the primary line, but it doesn't return a point on the second. the same bugs happen in both methods, so I'm really not sure what I'm doing wrong.
How can I fix this?
EDIT: Actually, this code works fine; my visualization code had an error.
I believe you've confused what the location() and vector() methods return. Unless i'm mistaken the location().x() gives you a point on the line created by the vector while vector().x() gives you the magnitude of the x value of the vector. (e.g. a horizontal has a vector().y() of 0)
You are adding the magnitude of the vector to the starting point. Instead try multiplying the starting point by the magnitude
float x2 = x1 * line1.vector().x();
float y2 = y1 * line1.vector().y();
As it turns out, the code was working; my visualization code had a bug in it. My bad.

Categories

Resources