Calculating the slope of a series of values - java

I have 2 arrays of equal length. The following function attempts to calculate the slope using these arrays. It returns the average of the slope between each points. For the following data set, I seem to be getting different values than Excel and Google Docs.
double[] x_values = { 1932, 1936, 1948, 1952, 1956, 1960, 1964, 1968,
1972, 1976, 1980 };
double[] y_values = { 197, 203, 198, 204, 212, 216, 218, 224, 223, 225,
236 };
public static double getSlope(double[] x_values, double[] y_values)
throws Exception {
if (x_values.length != y_values.length)
throw new Exception();
double slope = 0;
for (int i = 0; i < (x_values.length - 1); i++) {
double y_2 = y_values[i + 1];
double y_1 = y_values[i];
double delta_y = y_2 - y_1;
double x_2 = x_values[i + 1];
double x_1 = x_values[i];
double delta_x = x_2 - x_1;
slope += delta_y / delta_x;
}
System.out.println(x_values.length);
return slope / (x_values.length);
}
Output
Google: 0.755
getSlope(): 0.962121212121212
Excel: 0.7501

I bet the other two methods are computing the least-squares fit, whereas you are not.
When I verify this conjecture using R, I too get the slope of about 0.755:
> summary(lm(y~x))
Call:
lm(formula = y ~ x)
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -1.265e+03 1.793e+02 -7.053 5.97e-05 ***
x 7.551e-01 9.155e-02 8.247 1.73e-05 ***
The relevant number is the 7.551e-01. It is also worth noting that the line has an intercept of about -1265.
Here is a picture of the least-squares fit:
As to implementing this in your code, see Compute least squares using java

This function will not help you much, as it does not take into account the breadths of the various line segments. Consider the differences in applying it to the points (0,0), (1000,1000), and (1001, 2000) versus (0,0), (1,1), and (2, 1001). Both cases have successive slopes 1 and 1000, yet they look greatly different.
You need to implement the method of least squares: http://en.wikipedia.org/wiki/Least_squares to find the line that best approximates your data set.
One more piece of advice: never throw a java.lang.Exception. Always choose a more-specific exception, even if you must write the class yourself. People using your code will need to handle java.lang.Exception, which interferes badly with their other code.

Edit: use Apache Commons Math class SimpleRegression if that's an option.
Else, here's a method that calculates slope and also intercept, should yield the same results as excel and apache:
private static double intercept(List<Double> yList, List<Double> xList) {
if (yList.size() != xList.size())
throw new IllegalArgumentException("Number of y and x must be the same");
if (yList.size() < 2)
throw new IllegalArgumentException("Need at least 2 y, x");
double yAvg = average(yList);
double xAvg = average(xList);
double sumNumerator = 0d;
double sumDenominator = 0d;
for (int i = 0; i < yList.size(); i++) {
double y = yList.get(i);
double x = xList.get(i);
double yDiff = y - yAvg;
double xDiff = x - xAvg;
double numerator = xDiff * yDiff;
double denominator = xDiff * xDiff;
sumNumerator += numerator;
sumDenominator += denominator;
}
double slope = sumNumerator / sumDenominator;
double intercept = yAvg - (slope * xAvg);
return intercept;
}
private static double average(Collection<Double> doubles) {
return doubles.stream().collect(Collectors.averagingDouble(d -> d));
}
Sources:
Excel doc for SLOPE
Excel doc for INTERCEPT

You should be dividing by x_values.length - 1 . Number of slopes is pairwise.
Edit : Wiki example in my comments shows how to calculate the alpha and beta which determines the slope of the linear regression line.

Related

Simple polygon from unordered points

I've been trying to create an algorithm for finding the order of points in a simple polygon.
The aim is when given points on a 2D plane (there is always possible to form a simple polygon btw) I output the order of points in a valid simple polygon. All points must be part of said polygon.
I've somewhat achieved this, but it fails for some test cases. The way I have done this is by finding the geometrical centre
int centerX = (lowX + highX) / 2;
int centerY = (lowY + highY) / 2;
Point center = new Point(centerX, centerY, -1);
and then sorting all points by their polar angle.
Collections.sort(points, (a, b) -> {
if(a == b || a.equals(b)) {
return 0;
}
double aTheta = Math.atan2((long)a.y - center.y, (long)a.x - center.x);
double bTheta = Math.atan2((long)b.y - center.y, (long)b.x - center.x);
if(aTheta < bTheta) {
return -1;
}
else if(aTheta > bTheta) {
return 1;
}
else {
double aDist = Math.sqrt((((long)center.x - a.x) * ((long)center.x - a.x)) +
(((long)center.y - a.y) * ((long)center.y - a.y)));
double bDist = Math.sqrt((((long)center.x - b.x) * ((long)center.x - b.x)) +
(((long)center.y - b.y) * ((long)center.y - b.y)));
if (aDist < bDist) {
return -1;
}
else {
return 1;
}
}
});
I'm struggling with finding out what makes this break for some of the test cases. Any help or pointers are greatly appreciated! Also wondering if there are any efficient, yet not overly complicated algorithms that can perform this.
UPDATE
I've found one of the failing test cases: When given the points (101, 101), (100, 100), (105, 100), (103, 100), (107, 100), (102, 100), (109, 100) Labeled 0 to 9 respectively
My program outputs 2 4 6 0 3 5 1 but it is not a valid simple polygon
It should be a permutation of 1 0 6 4 2 3 5
Here's a Java implementation of the nice answer already provided by Reblochon Masque.
Note that instead of using any trig functions to calculate angles we use a comparison of the relative orientation (or turn direction) from the min point to each of the two points being compared. Personally I find this more elegant than using angles, but others may disagree. However, as with any calculations based on double the orient2D method is susceptible to errors in rounding.
Also, when there's a tie based on orientation, because the min point and the two points are collinear, we break the tie by considering the relative ordering of the two points. This means that we'll visit points in order, with no "switchbacks", which I think is preferable.
static List<Point2D> simplePolygon(Collection<Point2D> points)
{
final Point2D min = minPoint2D(points);
List<Point2D> simple = new ArrayList<>(points);
Collections.sort(simple, (p1, p2) ->
{
int cmp = orient2D(min, p2, p1);
if(cmp == 0)
cmp = order2D(p1, p2);
return cmp;
});
return simple;
}
// return lowest, leftmost point
static Point2D minPoint2D(Collection<Point2D> points)
{
Point2D min = null;
for(Point2D p : points)
if(min == null || order2D(p, min) < 0) min = p;
return min;
}
// order points by increasing y, break ties by increasing x
static int order2D(Point2D p1, Point2D p2)
{
if(p1.getY() < p2.getY()) return -1;
else if(p1.getY() > p2.getY()) return 1;
else if(p1.getX() < p2.getX()) return -1;
else if(p1.getX() > p2.getX()) return 1;
else return 0;
}
// Does p involve a CCW(+1), CW(-1) or No(0) turn from the line p1-p2
static int orient2D(Point2D p1, Point2D p2, Point2D p)
{
double dx = p2.getX() - p1.getX();
double dy = p2.getY() - p1.getY();
double px = p.getX() - p1.getX();
double py = p.getY() - p1.getY();
double dot = py * dx - px * dy;
return dot < 0 ? -1 : dot > 0 ? 1 : 0;
}
Test:
int[] a = {101, 101, 100, 100, 105, 100, 103, 100, 107, 100, 102, 100, 109, 100};
List<Point2D> points = new ArrayList<>();
for(int i=0; i<a.length; i+=2)
points.add(new Point2D.Double(a[i], a[i+1]));
List<Point2D> simple = simplePolygon(points);
for(Point2D p : simple) System.out.println(p);
Output:
Point2D.Double[100.0, 100.0]
Point2D.Double[102.0, 100.0]
Point2D.Double[103.0, 100.0]
Point2D.Double[105.0, 100.0]
Point2D.Double[107.0, 100.0]
Point2D.Double[109.0, 100.0]
Point2D.Double[101.0, 101.0]
Which I believe is correct.
here is an easy to implement O(n logn) algorithm that is guaranteed to produce a simple polygon (no edge crossings)
1- find the point the most south, (and the most westwards if you have a tie with the y values).
2- Sort all points based on their angle between this most south point, and the horizontal line.
3- the ordered sequence is a simple polygon.
In some rare cases, some points may not form a vertex, but be included in an edge, if they are collinear at the same angle.

I am trying to calculate sine of an angle without using the Math.sin() in java

I am trying to calculate sine of an angle without using the Math.sin(). I got stuck in it's equation as I keep getting the wrong results
note I have a method that changes the angle from degrees to radians
public static double sin(double x, int precision) {
//this method is simply the sine function
double answer = 1, power = 1;
int n = 2,factorial = 1;
while (n<=precision) {
power = (power * x * x *-1) +1 ;
factorial = (factorial * (n +1))* (n-1);
answer = answer + ((power/factorial ));
n = n + 2;
}
return answer;
}
It looks like you're attempting to calculate the sine of angle given in radians using the Maclaurin series, a special case of Taylor series.
sin(x) = x - x^3/3! + x^5/5! - x^7/7! + ...
Your initial answer is 1 when it should be x. Your initial power is 1 when it should be x also.
double answer = x, power = x;
For some reason you're adding one to the power part of the result when you shouldn't be.
power = (power * x * x * -1);
You'll also need to fix your factorial calculation. Multiply by n + 1 and n, not n + 1 and n - 1.
factorial = (factorial * (n + 1)) * (n);
With these fixes, testing:
for (double angle = 0; angle <= Math.PI; angle += Math.PI / 4)
{
System.out.println("sin(" + angle + ") = " + sin(angle, 10));
}
The results are pretty good considering the limitations of precision for floating point arithmetic.
sin(0.0) = 0.0
sin(0.7853981633974483) = 0.7071067811796194
sin(1.5707963267948966) = 0.999999943741051
sin(2.356194490192345) = 0.7070959900908971
sin(3.141592653589793) = -4.4516023820965686E-4
Note that this will get more inaccurate as the values of x get larger, not just because of the inaccuracy to represent pi, but also because of the floating point calculations for adding and subtracting large values.

How do I fix this heart?

Seeing as Valentine's Day is fast approaching, I decided to create a heart. So I found this heart from mathematica.se:
I played around in Mathematica (solved for z, switching some variables around) to get this equation for the z-value of the heart, given the x and y values (click for full-size):
I faithfully ported this equation to Java, dealing with a couple out-of-bounds cases:
import static java.lang.Math.cbrt;
import static java.lang.Math.pow;
import static java.lang.Math.sqrt;
...
public static double heart(double xi, double yi) {
double x = xi;
double y = -yi;
double temp = 5739562800L * pow(y, 3) + 109051693200L * pow(x, 2) * pow(y, 3)
- 5739562800L * pow(y, 5);
double temp1 = -244019119519584000L * pow(y, 9) + pow(temp, 2);
//
if (temp1 < 0) {
return -1; // this is one possible out of bounds location
// this spot is the location of the problem
}
//
double temp2 = sqrt(temp1);
double temp3 = cbrt(temp + temp2);
if (temp3 != 0) {
double part1 = (36 * cbrt(2) * pow(y, 3)) / temp3;
double part2 = 1 / (10935 * cbrt(2)) * temp3;
double looseparts = 4.0 / 9 - 4.0 / 9 * pow(x, 2) - 4.0 / 9 * pow(y, 2);
double sqrt_body = looseparts + part1 + part2;
if (sqrt_body >= 0) {
return sqrt(sqrt_body);
} else {
return -1; // this works; returns -1 if we are outside the heart
}
} else {
// through trial and error, I discovered that this should
// be an ellipse (or that it is close enough)
return Math.sqrt(Math.pow(2.0 / 3, 2) * (1 - Math.pow(x, 2)));
}
}
The only problem is that when temp1 < 0, I cannot simply return -1, like I do:
if (temp1 < 0) {
return -1; // this is one possible out of bounds location
// this spot is the location of the problem
}
That's not the behavior of the heart at that point. As it is, when I try to make my image:
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import static java.lang.Math.cbrt;
import static java.lang.Math.pow;
import static java.lang.Math.sqrt;
public class Heart {
public static double scale(int x, int range, double l, double r) {
double width = r - l;
return (double) x / (range - 1) * width + l;
}
public static void main(String[] args) throws IOException {
BufferedImage img = new BufferedImage(1000, 1000, BufferedImage.TYPE_INT_RGB);
// this is actually larger than the max heart value
final double max_heart = 0.679;
double max = 0.0;
for (int x = 0; x < img.getWidth(); x++) {
for (int y = 0; y < img.getHeight(); y++) {
double xv = scale(x, img.getWidth(), -1.2, 1.2);
double yv = scale(y, img.getHeight(), -1.3, 1);
double heart = heart(xv, yv); //this isn't an accident
// yes I don't check for the return of -1, but still
// the -1 values return a nice shade of pink: 0xFFADAD
// None of the other values should be negative, as I did
// step through from -1000 to 1000 in python, and there
// were no negatives that were not -1
int r = 0xFF;
int gb = (int) (0xFF * (max_heart - heart));
int rgb = (r << 16) | (gb << 8) | gb;
img.setRGB(x, y, rgb);
}
}
ImageIO.write(img, "png", new File("location"));
}
// heart function clipped; it belongs here
}
I get this:
Look at that dip at the top! I tried changing that problematic -1 to a .5, resulting in this:
Now the heart has horns. But it becomes clear where that problematic if's condition is met.
How can I fix this problem? I don't want a hole in my heart at the top, and I don't want a horned heart. If I could clip the horns to the shape of a heart, and color the rest appropriately, that would be perfectly fine. Ideally, the two sides of the heart would come together as a point (hearts have a little point at the join), but if they curve together like shown in the horns, that would be fine too. How can I achieve this?
The problem is simple. If we look at that horseshoe region, we get imaginary numbers. For part of it, it should belong to our heart. In that region, if we were to evaluate our function (by math, not by programming), the imaginary parts of the function cancel. So it should look like this (generated in Mathematica):
Basically, the function for that part is almost identical; we just have to do arithmetic with complex numbers instead of real numbers. Here's a function that does exactly that:
private static double topOfHeart(double x, double y, double temp, double temp1) {
//complex arithmetic; each double[] is a single number
double[] temp3 = cbrt_complex(temp, sqrt(-temp1));
double[] part1 = polar_reciprocal(temp3);
part1[0] *= 36 * cbrt(2) * pow(y, 3);
double[] part2 = temp3;
part2[0] /= (10935 * cbrt(2));
toRect(part1, part2);
double looseparts = 4.0 / 9 - 4.0 / 9 * pow(x, 2) - 4.0 / 9 * pow(y, 2);
double real_part = looseparts + part1[0] + part2[0];
double imag_part = part1[1] + part2[1];
double[] result = sqrt_complex(real_part, imag_part);
toRect(result);
// theoretically, result[1] == 0 should work, but floating point says otherwise
if (Math.abs(result[1]) < 1e-5) {
return result[0];
}
return -1;
}
/**
* returns a specific cuberoot of this complex number, in polar form
*/
public static double[] cbrt_complex(double a, double b) {
double r = Math.hypot(a, b);
double theta = Math.atan2(b, a);
double cbrt_r = cbrt(r);
double cbrt_theta = 1.0 / 3 * (2 * PI * Math.floor((PI - theta) / (2 * PI)) + theta);
return new double[]{cbrt_r, cbrt_theta};
}
/**
* returns a specific squareroot of this complex number, in polar form
*/
public static double[] sqrt_complex(double a, double b) {
double r = Math.hypot(a, b);
double theta = Math.atan2(b, a);
double sqrt_r = Math.sqrt(r);
double sqrt_theta = 1.0 / 2 * (2 * PI * Math.floor((PI - theta) / (2 * PI)) + theta);
return new double[]{sqrt_r, sqrt_theta};
}
public static double[] polar_reciprocal(double[] polar) {
return new double[]{1 / polar[0], -polar[1]};
}
public static void toRect(double[]... polars) {
for (double[] polar: polars) {
double a = Math.cos(polar[1]) * polar[0];
double b = Math.sin(polar[1]) * polar[0];
polar[0] = a;
polar[1] = b;
}
}
To join this with your program, simply change your function to reflect this:
if (temp1 < 0) {
return topOfHeart(x, y, temp, temp1);
}
And running it, we get the desired result:
It should be pretty clear that this new function implements exactly the same formula. But how does each part work?
double[] temp3 = cbrt_complex(temp, sqrt(-temp1));
cbrt_complex takes a complex number in the form of a + b i. That's why the second argument is simply sqrt(-temp1) (notice that temp1 < 0, so I use - instead of Math.abs; Math.abs is probably a better idea). cbrt_complex returns the cube root of the complex number, in polar form: r eiθ. We can see from wolframalpha that with positive r and θ, we can write an n-th root of a complex numbers as follows:
And that's exactly how the code for the cbrt_complex and sqrt_complex work. Note that both take a complex number in rectangular coordinates (a + b i) and return a complex number in polar coordinates (r eiθ)
double[] part1 = polar_reciprocal(temp3);
It is easier to take the reciprocal of a polar complex number than a rectangular complex number. If we have r eiθ, its reciprocal (this follows standard power rules, luckily) is simply 1/r e-iθ. This is actually why we are staying in polar form; polar form makes multiplication-type operations easier, and addition type operations harder, while rectangular form does the opposite.
Notice that if we have a polar complex number r eiθ and we want to multiply by a real number d, the answer is as simple as d r eiθ.
The toRect function does exactly what it seems like it does: it converts polar coordinate complex numbers to rectangular coordinate complex numbers.
You may have noticed that the if statement doesn't check that there is no imaginary part, but only if the imaginary part is really small. This is because we are using floating point numbers, so checking result[1] == 0 will likely fail.
And there you are! Notice that we could actually implement the entire heart function with this complex number arithmetic, but it's probably faster to avoid this.

Java Guassian Distribution-Bell Curve [duplicate]

This question already has answers here:
Draw Gaussian curve in Java
(2 answers)
Closed 7 years ago.
I have calculated mean and SD of a set of values. Now I need to draw a bell curve using those value to show the normal distribution in JAVA Swing. How do i proceed with this situation.
List : 204 297 348 528 681 684 785 957 1044 1140 1378 1545 1818
Total count : 13
Average value (Mean): 877.615384615385
Standard deviation (SD) : 477.272626245539
If i can get the x and y cordinates I can do it, but how do i get those values?
First you need to calculate the variance for the set. The variance is computed as the average squared deviation of each number from its mean.
double variance(double[] population) {
long n = 0;
double mean = 0;
double s = 0.0;
for (double x : population) {
n++;
double delta = x – mean;
mean += delta / n;
s += delta * (x – mean);
}
// if you want to calculate std deviation
return (s / n);
}
Once you have that you can choose x depending on your graph resolution compared to your value set spread and plug it in to the following equation to get y.
protected double stdDeviation, variance, mean;
public double getY(double x) {
return Math.pow(Math.exp(-(((x - mean) * (x - mean)) / ((2 * variance)))), 1 / (stdDeviation * Math.sqrt(2 * Math.PI)));
}
To display the resulting set: say we take the population set you laid out and decide you want to show x=0 to x=2000 on a graph with an x resolution of 1000 pixels. Then you would plug in a loop (int x = 0; x <= 2000; x = 2) and feed those values into the equation above to get your y values for the pair. Since the y you want to show is 0-1 then you map these values to whatever you want your y resolution to be with appropriate rounding behavior so your graph doesn't end up too jaggy. So if you want your y resolution to be 500 pixels then you set 0 to 0 and 1 to 500 and .5 to 250 etc. etc. This is a contrived example and you might need a lot more flexibility but I think it illustrates the point. Most graphing libraries will handle these little things for you.
Here's an example of plotting some Gaussian curves using XChart. The code can be found here. Disclaimer: I'm the creator of the XChart Java charting library.
public class ThemeChart03 implements ExampleChart {
public static void main(String[] args) {
ExampleChart exampleChart = new ThemeChart03();
Chart chart = exampleChart.getChart();
new SwingWrapper(chart).displayChart();
}
#Override
public Chart getChart() {
// Create Chart
Chart_XY chart = new ChartBuilder_XY().width(800).height(600).theme(ChartTheme.Matlab).title("Matlab Theme").xAxisTitle("X").yAxisTitle("Y").build();
// Customize Chart
chart.getStyler().setPlotGridLinesVisible(false);
chart.getStyler().setXAxisTickMarkSpacingHint(100);
// Series
List<Integer> xData = new ArrayList<Integer>();
for (int i = 0; i < 640; i++) {
xData.add(i);
}
List<Double> y1Data = getYAxis(xData, 320, 60);
List<Double> y2Data = getYAxis(xData, 320, 100);
List<Double> y3Data = new ArrayList<Double>(xData.size());
for (int i = 0; i < 640; i++) {
y3Data.add(y1Data.get(i) - y2Data.get(i));
}
chart.addSeries("Gaussian 1", xData, y1Data);
chart.addSeries("Gaussian 2", xData, y2Data);
chart.addSeries("Difference", xData, y3Data);
return chart;
}
private List<Double> getYAxis(List<Integer> xData, double mean, double std) {
List<Double> yData = new ArrayList<Double>(xData.size());
for (int i = 0; i < xData.size(); i++) {
yData.add((1 / (std * Math.sqrt(2 * Math.PI))) * Math.exp(-(((xData.get(i) - mean) * (xData.get(i) - mean)) / ((2 * std * std)))));
}
return yData;
}
}
The resulting plot looks like this:

Calculating the angle between two lines without having to calculate the slope? (Java)

I have two Lines: L1 and L2. I want to calculate the angle between the two lines. L1 has points: {(x1, y1), (x2, y2)} and L2 has points: {(x3, y3), (x4, y4)}.
How can I calculate the angle formed between these two lines, without having to calculate the slopes? The problem I am currently having is that sometimes I have horizontal lines (lines along the x-axis) and the following formula fails (divide by zero exception):
arctan((m1 - m2) / (1 - (m1 * m2)))
where m1 and m2 are the slopes of line 1 and line 2 respectively. Is there a formula/algorithm that can calculate the angles between the two lines without ever getting divide-by-zero exceptions? Any help would be highly appreciated.
This is my code snippet:
// Calculates the angle formed between two lines
public static double angleBetween2Lines(Line2D line1, Line2D line2)
{
double slope1 = line1.getY1() - line1.getY2() / line1.getX1() - line1.getX2();
double slope2 = line2.getY1() - line2.getY2() / line2.getX1() - line2.getX2();
double angle = Math.atan((slope1 - slope2) / (1 - (slope1 * slope2)));
return angle;
}
Thanks.
The atan2 function eases the pain of dealing with atan.
It is declared as double atan2(double y, double x) and converts rectangular coordinates (x,y) to the angle theta from the polar coordinates (r,theta)
So I'd rewrite your code as
public static double angleBetween2Lines(Line2D line1, Line2D line2)
{
double angle1 = Math.atan2(line1.getY1() - line1.getY2(),
line1.getX1() - line1.getX2());
double angle2 = Math.atan2(line2.getY1() - line2.getY2(),
line2.getX1() - line2.getX2());
return angle1-angle2;
}
Dot product is probably more useful in this case. Here you can find a geometry package for Java which provides some useful helpers. Below is their calculation for determining the angle between two 3-d points. Hopefully it will get you started:
public static double computeAngle (double[] p0, double[] p1, double[] p2)
{
double[] v0 = Geometry.createVector (p0, p1);
double[] v1 = Geometry.createVector (p0, p2);
double dotProduct = Geometry.computeDotProduct (v0, v1);
double length1 = Geometry.length (v0);
double length2 = Geometry.length (v1);
double denominator = length1 * length2;
double product = denominator != 0.0 ? dotProduct / denominator : 0.0;
double angle = Math.acos (product);
return angle;
}
Good luck!
dx1 = x2-x1;
dy1 = y2-y1;
dx2 = x4-x3;
dy2 = y4-y3;
d = dx1*dx2 + dy1*dy2; // dot product of the 2 vectors
l2 = (dx1*dx1+dy1*dy1)*(dx2*dx2+dy2*dy2) // product of the squared lengths
angle = acos(d/sqrt(l2));
The dot product of 2 vectors is equal to the cosine of the angle time the length of both vectors. This computes the dot product, divides by the length of the vectors and uses the inverse cosine function to recover the angle.
Maybe my approach for Android coordinates system will be useful for someone (used Android PointF class to store points)
/**
* Calculate angle between two lines with two given points
*
* #param A1 First point first line
* #param A2 Second point first line
* #param B1 First point second line
* #param B2 Second point second line
* #return Angle between two lines in degrees
*/
public static float angleBetween2Lines(PointF A1, PointF A2, PointF B1, PointF B2) {
float angle1 = (float) Math.atan2(A2.y - A1.y, A1.x - A2.x);
float angle2 = (float) Math.atan2(B2.y - B1.y, B1.x - B2.x);
float calculatedAngle = (float) Math.toDegrees(angle1 - angle2);
if (calculatedAngle < 0) calculatedAngle += 360;
return calculatedAngle;
}
It return positive value in degrees for any quadrant: 0 <= x < 360
You can checkout my utility class here
The formula for getting the angle is tan a = (slope1-slope2)/(1+slope1*slope2)
You are using:
tan a = (slope1 - slope2) / (1 - slope1 * slope2)
So it should be:
double angle = Math.atan((slope1 - slope2) / (1 + slope1 * slope2));
First, are you sure the brackets are in the right order? I think (could be wrong) it should be this:
double slope1 = (line1.getY1() - line1.getY2()) / (line1.getX1() - line1.getX2());
double slope2 = (line2.getY1() - line2.getY2()) / (line2.getX1() - line2.getX2());
Second, there are two things you could do for the div by zero: you could catch the exception and handle it
double angle;
try
{
angle = Math.atan((slope1 - slope2) / (1 - (slope1 * slope2)));
catch (DivideByZeroException dbze)
{
//Do something about it!
}
...or you could check that your divisors are never zero before you attempt the operation.
if ((1 - (slope1 * slope2))==0)
{
return /*something meaningful to avoid the div by zero*/
}
else
{
double angle = Math.atan((slope1 - slope2) / (1 - (slope1 * slope2)));
return angle;
}
Check this Python code:
import math
def angle(x1,y1,x2,y2,x3,y3):
if (x1==x2==x3 or y1==y2==y3):
return 180
else:
dx1 = x2-x1
dy1 = y2-y1
dx2 = x3-x2
dy2 = y3-y2
if x1==x2:
a1=90
else:
m1=dy1/dx1
a1=math.degrees(math.atan(m1))
if x2==x3:
a2=90
else:
m2=dy2/dx2
a2=math.degrees(math.atan(m2))
angle = abs(a2-a1)
return angle
print angle(0,4,0,0,9,-6)
dx1=x2-x1 ; dy1=y2-y1 ; dx2=x4-x3 ;dy2=y4-y3.
Angle(L1,L2)=pi()/2*((1+sign(dx1))* (1-sign(dy1^2))-(1+sign(dx2))*(1-sign(dy2^2)))
+pi()/4*((2+sign(dx1))*sign(dy1)-(2+sign(dx2))*sign(dy2))
+sign(dx1*dy1)*atan((abs(dx1)-abs(dy1))/(abs(dx1)+abs(dy1)))
-sign(dx2*dy2)*atan((abs(dx2)-abs(dy2))/(abs(dx2)+abs(dy2)))

Categories