Calculate angle between two lines - java

After looking at the answers provided in this question, I created the following method:
private int angleOf(float x1, float x2, float y1, float y2) {
final double deltaY = (y1 - y2);
final double deltaX = (x2 - x1);
final double result = Math.toDegrees(Math.atan2(deltaY, deltaX));
return (int) ((result < 0) ? (360d + result) : result);
}
by using the above I will get the angle of each line , then I draw the text to my canvas, as shown below:
int topLine = angleOf(this.mPoints[5].x, this.mPoints[4].x, this.mPoints[5].y, this.mPoints[4].y);
int bottomLine = angleOf(this.mPoints[5].x, this.mPoints[6].x, this.mPoints[5].y, this.mPoints[6].y);
canvas.drawText(String.valueOf(360 - bottomLine + topLine)+"°", this.mPoints[5].x - 80.0f, this.mPoints[5].y, this.mTextPaint);
The above works fine, here is a example of my result:
The problem I have is that the angle is measured from the x-axis and increasing anti-clockwise, as shown below:
When the bottom line or the top line "crosses" the 0° (parallel to the x-axis), I would then get an incorrect angle.
Here is another image to demonstrate this issue:
The angle between the blue lines are 90°, but instead I get 450°. This happens because of the calculation I used 360 - bottomLine + topLine.
Can someone please suggest a solution to this issue.
Thank you.

You can use like this,out put value is radian
coordinate point (0,0) other points (x1,y1) ,(x2,y2)
atan() = tan invers
private double angleOfRadian(float x1, float x2, float y1, float y2) {
return java.lang.Math.atan(y2/x2)-java.lang.Math.atan(y1/x1);
}

Use this method to calculate it properly:
private double angleOfDegrees(float x0, float y0, float x1, float y1) {
double angle2 = Math.atan2(y1,x1);
double angle1 = Math.atan2(y0,x0);
return Math.toDegrees(angle2 - angle1) + 360) % 360;
}

Related

Java/Processing calculations returning "NaN" and "Infinity"

I am trying to make simulation of the three-body problem in Processing/Java. I have created a Planet object and defined several functions to calculate the attraction, the forces, and the speeds of the Planets. The program runs without any errors. The hitch is that the calculation are returning Infinity and
NaN outputs.
I haven't found any divide by zero errors.
Why is it doing this?
float simulationTime = 0.01;
float earthMass = pow(10,24)*5.972;
Planet[] bodies = {new Planet(100,200, 0, 0,earthMass/2),
new Planet(400,500, 0, 0,earthMass/2),
new Planet(800,200, 0, 0,earthMass/2)};
int size = 500;
float G = 6.674*pow(10, -11);
float gravAttract(float mass1, float mass2, float x1, float y1, float x2, float y2) {
float force = G*mass1*mass2/pow(dist1(x1, y1, x2, y2), 2);
//println(pow(dist1(x1, y1, x2, y2), 2));
//println(force);
return force;
}
float attract(Planet one,Planet two){
float force = G*one.mass*two.mass/pow(dist1(one.xpos,one.ypos,two.xpos,two.ypos),2);
println(one.xpos,two.xpos,one.xspeed,two.xspeed);
return force;
}
float[] forceXY(int body){
float[] xy = {0,0};
for (int ii = 0; ii<bodies.length; ii = ii+1){
if (ii == body){
continue;
}
else{
xy[0] = xy[0]+attract(bodies[body],bodies[ii])*
(bodies[ii].xpos-bodies[body].xpos)/dist1(bodies[body].xpos,bodies[body].ypos,bodies[ii].xpos,bodies[ii].ypos);
xy[1] = xy[1]+attract(bodies[body],bodies[ii])*
(bodies[ii].ypos-bodies[body].ypos)/dist1(bodies[body].xpos,bodies[body].ypos,bodies[ii].xpos,bodies[ii].ypos);
println(xy);
}
}
return xy;
}
float dist1(float x1,float y1,float x2,float y2){
float x = dist(x1,y1,x2,y2);
x = x*149.6*pow(10,7);
//println(x1,y1,x2,y2);
return x;
}
class Planet {
float xpos;
float ypos;
float xspeed;
float yspeed;
float mass;
Planet(float a, float b, float c, float d, float e) {
xpos = a;
ypos = b;
xspeed = c;
yspeed = d;
mass = e;
}
void update(float xforce, float yforce) {
//println("xy",xpos,ypos);
float xa = xforce/mass;
float ya = yforce/mass;
xspeed = xspeed + xa*simulationTime;
yspeed = yspeed + ya*simulationTime;
xpos = xpos + xspeed*simulationTime;
ypos = ypos + yspeed*simulationTime;
}
}
void setup() {
size(1000, 1000);
frameRate(1);
}
void draw() {
background(0);
for (int ii = 0; ii < bodies.length; ii = ii+1){
float[] asdf = new float[2];
asdf = forceXY(ii);
circle(bodies[ii].xpos,bodies[ii].ypos,10);
bodies[ii].update(asdf[0],asdf[1]);
}
}
I see you're trying to do the calculations using the real physical values. The problem with that is that the astronomical masses, distances and forces are astronomical, not just literally but also figuratively. The numbers are so big that the results of the intermediate calculations cannot be represented using the limited range of the float data type.
The solution is to change the units. For example, instead of using meters, kilograms, and seconds, measure the distance in "astronomical units" (distance between Earth and Sun), mass in multiples of Earth masses, and time in years. Or use the standard "astronomical system of units". Most importantly, this changes the value of the gravitational constant G.
If you're not too attached to making a simulation that lets you predict the real positions of the planets, it's much easier to just "wing it" and set G=1, set the masses to small numbers, and play around with the velocities. You'll see it's very easy to come up with a realistic simulation.

How do I calculate the coordinates of the points of an helix?

The following code is called every 50ms.
// Start point
private double x;
private double y;
private double z;
private double y1;
#Override
public void run() {
double x1 = Math.cos(y1);
double z1 = Math.sin(y1);
double y2 = 4D - y1;
double x2 = Math.sin(y2);
double z2 = Math.cos(y2);
// First new point
double pX1 = x + x1;
double pY1 = y + y1;
double pZ1 = z + z1;
// Second new point
double pX2 = x + x2;
double pY2 = y + y2;
double pZ2 = z + z2;
if (y1 > 4D) {
y1 = 0D;
} else {
y1 = y1 + 0.1D;
}
}
Here is the output in a game. It generates two helices.
I cannot control more than the radius.
I am looking for code I can easily customize to fit my preferences.
How do I control the following aspects?
How fast the helix rises.
Where the helix begins.
helix is circular shape with 'linear' movement of the plane
you use plane xz as helix base and y axis as height
so you need:
r - radius
d - distance between two screws (the y movement after full circle)
t - parameter <0,1> determining the position on helix
h0,h1 - start end height of helix (y-axis)
a0 - angular start position [rad]
Now how to get the point on helix as function of parameter these parameters
aa=fabs(h1-h0)*2.0*M_PI/d; // angular speed coefficient
// if you need opposite angular direction then add aa=-aa;
x=r*cos(a0+aa*t);
z=r*sin(a0+aa*t);
y=h0+((h1-h0)*t);
aa can be precomputed once
now if t=0.0 then you get the start point of helix
if t=1.0 then you got the endpoint of helix
so speed is just how much you add to t during animation per timer cycle
d controls number of screw loops
h1-h0 is the helix height
code is in C++ (sorry I am not a JAVA coder)
One part of the helix begins at:
(x, y, z) = (1.0, 0.0, 0.0)
And the other at:
(x, y, z) = (-0.8, 4.0, -0.7)
And the particle rises at a rate of 0.1 (from y1 = y1 + 0.1D).
So, to control how fast the particles rise, just change this value.
To control where the helix begins you need to change the angle. For example, add some value to the sines and cosines. Like this:
Math.cos(y1 + dy);
To make more rotations before restarting from the ground you can multiply the angle. Make it twice as fast:
Math.cos(2 * y1);
Helix is circular shape with progressive Y value.
// Start point
private double x;
private double y;
private double z;
private double degree;
private double rY;
#Override
public void run() {
// We use the same formula that is used to find a point of a circumference
double rX = Math.cos(degree);
double rZ = Math.sin(degree);
// New point
double pX = x + rX;
double pY = y + rY;
double pZ = z + rZ;
if (degree > 2D * Math.PI) {
degree = 0D;
} else {
degree = degree + 0.2D;
}
if (pY > 2D) {
pY = 0D;
} else {
pY = pY + 0.02D;
}
}

Check program debug

So I finished up a program that recursively draws lines which takes an argument "n" to define the depth of the recursion. I have 2 functions, one which draws the relatively left line and another which draws the relatively right one. I tested it ant it seems to work for the first 4 levels, but then either the lines become too small to accurately represent or there's something wrong with my code because the breaks between the lines seem to become arbitrary. Was hoping somebody could test my code and see if they could find what the problem is.
The following image is of depth 10.
EDIT: fixed a part of code, still need help though
public class Art
{
//draws the relatively left line
public static void drawLeftLine(double x0, double y0, double x1, double y1)
{
//define new x coordinate for line
//double x2 = (1/3.0)*(x1 - x0);
//color of line
StdDraw.setPenColor(StdDraw.BLUE);
//draw line by adding new x coord to original
StdDraw.line(x0, y0, x1, y1);
}
//draw relatively right line
public static void drawRightLine(double x0, double y0, double x1, double y1)
{
//define new x coord for line
//double x2 = (2/3.0)*(x1 - x0);
//color of line
StdDraw.setPenColor(StdDraw.BLUE);
//draw line by adding new x coord to original
StdDraw.line(x0, y0, x1, y1);
}
public static void cantor(int n, double x0, double y0, double x1, double y1)
{
if (n == 0)
return;
drawLeftLine(x0, y0, x1, y1);
drawRightLine(x0, y0, x1, y1);
y0 = y0 - 0.1;
y1 = y1 - 0.1;
cantor(n-1, x0, y0, x0 + ((x1 - x0))/3.0, y1); //left
cantor(n-1, (2.0/ 3) * (x1 - x0) + x0, y0, x1, y1); //right
}
public static void main(String[] args)
{
//change n into integer (depth)
int n = Integer.parseInt(args[0]);
//specify inital values for line
double x0 = 0;
double y0 = 0.9;
double x1 = 0.9;
double y1 = 0.9;
//recursive function cantor
cantor(n, x0, y0, x1, y1);
}
}
I think that the drawing looks incorrect because the of the fact that all of the nice double values are being approximated with discrete pixels causing unwanted overlap between the line segments (see EDIT at the bottom). Some comments about your code however :
1) You don't need the drawLeftLine and drawRightLine methods since currently they are drawing exactly the same thing. Since at each step you are calling cantor twice (once for each side of the deleted inner third), you have one call to cantor for each line segment that has to be drawn. As such I would put all of the drawing directly into the cantor method.
2) Since y0 and y1 are both always the same, I would reduce them to just a single y variable.
3) I would simplify the math for computing the new x0 and x1 values down to
double third = (x1 - x0) / 3;
cantor(n - 1, x0, x0 + third, y); // left
cantor(n - 1, x1 - third, x1, y); // right
4) Instead of decrementing the y value by 0.1 every time, you should have a global variable that decides the amount by which this should be decremented (otherwise if you try n > 10 things will break). This value can just be set to 1.0 / n.
5) You don't need to set the color of the pen every time you paint. You can set it just once in the main method.
6) StdDraw already sets a border around the picture you are drawing so there is no need to start your coordinates from 0.9 - you can use 1 instead.
Following these suggestions the code would look like this :
private static double yIncrement;
public static void cantor(int n, double x0, double x1, double y) {
if (n == 0)
return;
StdDraw.line(x0, y, x1, y);
y = y - yIncrement;
double third = (x1 - x0) / 3;
cantor(n - 1, x0, x0 + third, y); // left
cantor(n - 1, x1 - third, x1, y); // right
}
public static void main(String[] args) {
//change n into integer (depth)
int n = Integer.parseInt(args[0]);
// specify inital values for line
double x0 = 0;
double x1 = 1;
double y = 1;
yIncrement = 1.0 / n;
StdDraw.setPenColor(Color.BLUE);
// recursive function cantor
cantor(n, x0, x1, y);
}
EDIT : Playing around with the StdDraw canvas size, canvas scaling settings, and line segment endpoint rounding mode you can get a slightly better picture (the code below produces a picture that looks mostly correct down to the 8th level)
private static double yIncrement;
public static void cantor(int n, double x0, double x1, double y) {
if (n == 0)
return;
x0 = Math.ceil(x0);
x1 = Math.floor(x1);
StdDraw.line(x0, y, x1, y);
y = y - yIncrement;
double third = (x1 - x0) / 3;
cantor(n - 1, x0, x0 + third, y); // left
cantor(n - 1, x1 - third, x1, y); // right
}
public static void main(String[] args) {
// change n into integer (depth)
int n = Integer.parseInt(args[0]);
int width = 1920;
int height = 1080;
StdDraw.setCanvasSize(width, height);
// specify inital values for line
double x0 = 0;
double x1 = width;
double y = 1;
yIncrement = 1.0 / n;
StdDraw.setPenColor(Color.BLUE);
StdDraw.setXscale(0, width);
// recursive function cantor
cantor(n, x0, x1, y);
}
To display everything down to the tenth level with absolute correctness you would need a width of 3^9 pixels (19K pixels). For level 9 that's 3^8 = 6K. For level 8 that's 3^7 = 2k, which is why it looks almost correct with 1.9K pixel width and integer rounding.

Java Code Visual Representation of Slope in 3D Space

My last question involved getting the syntax right, this question is:
How should I best go about showing a 3D representation of a line between 2 points? I've calculated the slope, now I simply want to make a window appear and display a cube like this: http://www.wolframalpha.com/input/?i=slope+between+%282%2C6%2C1%29+and+%283%2C5%2C0%29
public static double calcSlope(Point p1, Point p2){
//math to calculate the slope
double slope1 = (p2.getY()- p1.getY())/(p2.getX()-p1.getX());
double angle1 = Math.atan(slope1);
double distance1 = (p2.getY()-p1.getY())/Math.sin(angle1);
System.out.println("distance: " + distance1);
double slopeFinal = 1/distance1;
return slopeFinal;
}
public static void main(String[]args){
double x1, x2, y1, y2, z1, z2;
x1 = 5;
x2 = 7.5;
y1 = 3.25;
y2 = 4;
z1 = 0;
z2 = 1;
Point point1 = new Point(x1, y1, z1);
//declaring new variables of class Point
Point point2 = new Point(x2, y2, z2);
//in Point y2 is = y, but y1 is also = y Point (x,y,z) serves as a placeholder where "x" is just
//a placeholder
double slope = calcSlope(point1, point2);
double angle = Math.atan(slope);
System.out.println("Your Slope is " + slope);
System.out.println("Angle of entry is " + angle);
}
Thats a BIG question, you're going to have to use some 3rd party library for 3D graphics as java doesn't natively support it*. I would suggest you look at jmonkey engine but thats just my personal preference: http://jmonkeyengine.com/.
*technically java3D does exist but it still doesn't come with java as standard and it is a largely abandoned project

Java Circle-Circle Collision Detection

Here is the circle class:
public class Circle {
private double radius;
private double x;
private double y;
}
How can I tell if two objects from this class (circles) are colliding?
P.S. Can you use the method that avoids taking a square root?
double xDif = x1 - x2;
double yDif = y1 - y2;
double distanceSquared = xDif * xDif + yDif * yDif;
boolean collision = distanceSquared < (radius1 + radius2) * (radius1 + radius2);
dx = x2 - x1;
dy = y2 - y1;
radiusSum = radius1 + radius2;
return dx * dx + dy * dy <= radiusSum * radiusSum; // true if collision
The link from #instanceofTom in the comments is better... with pictures.
The circles will touch when the distance between their centres is equal to the sum of their radii, or collide when the distance is less.
Since we are using absolute distance, it is Ok to compare the square of the distance between centres with the square of the sum of the radii.
Here's the updated Java solution:
public boolean hasCollision(Circle circle){
double xDiff = x - circle.getX();
double yDiff = y - circle.getY;
double distance = Math.sqrt((Math.pow(xDiff, 2) + Math.pow(yDiff, 2)));
return distance < (radius + circle.getRadius());
}

Categories

Resources