I'm trying to create a program where three random points in a circle are created and result in the creation of an inscribed triangle. However, the angles I'm getting are all screwed up
Here is my code:
public static void main(String[] args) {
double r = 40.0;
double angle1 = Math.random()* (2 * Math.PI);
double angle2 = Math.random()* (2 * Math.PI);
double angle3 = Math.random()* (2 * Math.PI);
double x_1 = r * Math.cos(angle1);
double y_1 = r * Math.sin(angle1);
double x_2 = r * Math.cos(angle2);
double y_2 = r * Math.sin(angle2);
double x_3 = r * Math.cos(angle3);
double y_3 = r * Math.sin(angle3);
System.out.println("The coordinates of the three points are:
(" + x_1 + ", " + y_1 + ")
(" + x_2 + ", " + y_2 + ")
(" + x_3 + ", " + y_3 + ")");
//Get length of each side
double distanceFrom1To2 = Math.sqrt(Math.pow(x_2 - x_1, 2) +
Math.pow(y_2 - y_1, 2));
double distanceFrom2To3 = Math.sqrt(Math.pow(x_3 - x_2, 2) +
Math.pow(y_3 - y_2, 2));
double distanceFrom3To1 = Math.sqrt(Math.pow(x_1 - x_3, 2) +
Math.pow(y_1 - y_3, 2));
//Get angles ***
double triangleAngle1 = Math.atan(distanceFrom1To2 / distanceFrom2To3);
double triangleAngle2 = Math.atan(distanceFrom2To3 / distanceFrom3To1);
double triangleAngle3 = Math.atan(distanceFrom3To1 / distanceFrom1To2);
System.out.println("The three angles are " + triangleAngle1 + " " +
triangleAngle2 + " " + triangleAngle3);
System.out.println(triangleAngle1 + triangleAngle2 + triangleAngle3);
}
I definitely know that the means of getting the angles are screwed up. Here is a sample run of my program:
The coordinates of the three points are: (5.224534224725408,
-39.65733528787168) (-29.696946087404676, 26.79722733944279)
(32.70889681040468, -23.02451018906371)
The three angles are 0.7545364726122026 1.18830825410364
0.40435068059871415
Total angle sum: 2.347195407314557
The angles all add up to much greater than Pi / 2 radians. I've considered the law of sines but you have to know at least one angle for that...
Figured it out
Here is the fixed code:
//Get length of each side
double a = Math.sqrt(Math.pow(x_2 - x_1, 2) + Math.pow(y_2 - y_1, 2)); // distance from 1 to 2
double b = Math.sqrt(Math.pow(x_3 - x_2, 2) + Math.pow(y_3 - y_2, 2)); // distance from 2 to 3
double c = Math.sqrt(Math.pow(x_1 - x_3, 2) + Math.pow(y_1 - y_3, 2)); // distance from 3 to 1
//Get angles ***
double triangleAngle1 = Math.acos((Math.pow(a, 2) + Math.pow(b, 2) - Math.pow(c, 2)) / (2 * a * b));
double triangleAngle2 = Math.acos((Math.pow(b, 2) + Math.pow(c, 2) - Math.pow(a, 2)) / (2 * c * b));
double triangleAngle3 = Math.acos((Math.pow(c, 2) + Math.pow(a, 2) - Math.pow(b, 2)) / (2 * a * c));
I changed it to use the law of cosines.
Related
I made a method in my Java code which translates a 3 coordinate vector into another 3 coordinate system basing my method on the rotation matrix which OpenGL used to have, here is the full method:
public static float[] rotateVector3 (float x, float y, float z, double rX, double rY, double rZ){
float[] ret = {x,y,z};
while(rX < 0){rX += Math.PI*2;}
while(rY < 0){rY += Math.PI*2;}
while(rZ < 0){rZ += Math.PI*2;}
while(rX >= Math.PI*2){rX -= Math.PI*2;}
while(rY >= Math.PI*2){rY -= Math.PI*2;}
while(rZ >= Math.PI*2){rZ -= Math.PI*2;}
//ret[0] *= 1;
ret[1] *= Math.cos(rX) - Math.sin(rX);
ret[2] *= Math.sin(rX) + Math.cos(rX);
ret[0] *= Math.cos(rY) + Math.sin(rY);
//ret[1] *= 1;
ret[2] *= - Math.sin(rY) + Math.cos(rY);
ret[0] *= Math.cos(rZ) - Math.sin(rZ);
ret[1] *= Math.sin(rZ) + Math.cos(rZ);
//ret[2] *= 1;
System.out.println("(" + x + " " + y + " " + z +") -> (" + rX + "º " + rY + "º " + rZ + "º) = (" + ret[0] + " " + ret[1] + " " + ret[2] + ")");
return ret;
}
However this method for some reason does not work well with the Z axis.
Let's assume for instance that i have 4 arrays representing vectors, each with 3 coordinates (XYZ respectively):
vecA = {50,50,1}, vecB = {50,-50,1}, vecC = {-50f,-50f,1}, vecD = {-50f,50f,1}
When I input those values in their respective order in the method, with each value of the rotation being {0,2,0} radians respectively, I get the following output:
(50.0 50.0 1.0) -> (0.0º 2.0º 0.0º) = (24.65753 50.0 -1.3254442)
(50.0 -50.0 1.0) -> (0.0º 2.0º 0.0º) = (24.65753 -50.0 -1.3254442)
(-50.0 -50.0 1.0) -> (0.0º 2.0º 0.0º) = (-24.65753 -50.0 -1.3254442)
(-50.0 50.0 1.0) -> (0.0º 2.0º 0.0º) = (-24.65753 50.0 -1.3254442)
Which does not make sense. As I am rotating in the Y axis, the vectors with the Y coordinates above zero should be farther that those with the negative Y coordinates, yet it always returns the same Z values regardless and I'm not entirely sure why, is there any correction that I am missing?
Figured it out, the correct way to do this is
public static float[] rotateVector3 (float x, float y, float z, double rX, double rY, double rZ, float aX, float aY, float aZ){
float[] ret = new float[3];
while(rX < 0){rX += Math.PI*2;}
while(rY < 0){rY += Math.PI*2;}
while(rZ < 0){rZ += Math.PI*2;}
while(rX >= Math.PI*2){rX -= Math.PI*2;}
while(rY >= Math.PI*2){rY -= Math.PI*2;}
while(rZ >= Math.PI*2){rZ -= Math.PI*2;}
double cosX = Math.cos(rX);
double cosY = Math.cos(rY);
double cosZ = Math.cos(rZ);
double sinX = Math.sin(rX);
double sinY = Math.sin(rY);
double sinZ = Math.sin(rZ);
double Axx = cosX*cosY;
double Axy = cosX*sinY*sinZ - sinX*cosZ;
double Axz = cosX*sinY*cosZ + sinX*sinZ;
double Ayx = sinX*cosY;
double Ayy = sinX*sinY*sinZ + cosX*cosZ;
double Ayz = sinX*sinY*cosZ - cosX*sinZ;
double Azx = -sinY;
double Azy = cosY*sinZ;
double Azz = cosY*cosZ;
x-=aX;
y-=aY;
z-=aZ;
ret[0] = (float) (Axx*x + Axy*y + Axz*z);
ret[1] = (float) (Ayx*x + Ayy*y + Ayz*z);
ret[2] = (float) (Azx*x + Azy*y + Azz*z);
System.out.println("(" + x + " " + y + " " + z +") -> (" + rX + "º " + rY + "º " + rZ + "º) = (" + ret[0] + " " + ret[1] + " " + ret[2] + ")");
return ret;
}
I'd explain how this works but that would imply that I actually know what I'm doing
The idea for the program is to establish a users name, ask for 3 variables that i assigned as doubles, and use these variables to calculate various equasions. My first error is on the line that states;
System.out.print ("The area of a trapazoid is ") + (h * (a + b)/2);
I am getting an 'error: not a statement' with an arrow pointing to the first plus sign. ANY help would be greatly appreciated.
import java.util.Scanner;
public class LineberryCorey
{
public static void main(String[] args)
{
Scanner stdIn = new Scanner(System.in);
String userName;
double a;
double b;
double h;
System.out.print ("What is your first name?");
userName = stdIn.nextString();
System.out.print ("Alright, " + userName + ". Give me a number.");
a = stdIn.nextDouble();
System.out.print ("give me another number.");
b = stdIn.nextDouble();
System.out.print ("Give me one more number.");
h = stdIn.nextDouble();
System.out.print ("using the date you provided...");
System.out.print ("The area of a trapazoid is ") + (h * (a + b)/2);
System.out.print ("The surface area of a box is ") + (2 * ((a * b) + (a * h) + (b * h)));
System.out.print ("The surface area of a sphere with radius ") + a + (" is ") + (4 * MATH.PI * (a * a));
System.out.print ("The volume of a sphere with radius ") + b + (" is ") + (4 * MATH.PI * (b * b * b) / 3);
System.out.print ("The volume of a spherical cap is ") + (MATH.PI * (h * h) * (3 * a - h) / 3);
System.out.print ("The volume of a frustum is ") + (MATH.PI * h * ((a * a) + (a * b) + (b * b)) / 3);
System.out.print ("The volume of a torus with radii of ") + a + (" and ") + b + (" is "((MATH.PI * MATH.PI) *
(((a + b) * (b - a)) * ((a + b) * (b - a))) / 4);
}
}
Correct all System.out.print() syntax:
//correct the code:
System.out.print ("The area of a trapazoid is" + (h * (a + b)/2));
System.out.print ("The surface area of a box is " + (2 * ((a * b) + (a * h) + (b * h))));
System.out.print ("The surface area of a sphere with radius " + a + " is " + (4 * MATH.PI * (a * a)));
System.out.print ("The volume of a sphere with radius " + b + " is " + (4 * MATH.PI * (b * b * b) / 3));
System.out.print ("The volume of a spherical cap is " + (MATH.PI * (h * h) * (3 * a - h) / 3));
System.out.print ("The volume of a frustum is " + (MATH.PI * h * ((a * a) + (a * b) + (b * b)) / 3));
Why you are concatenating sysout statements,
(" is ")// here parenthesis not required.
We are trying to get the cos value between v and u but we are getting results much higher than 1 or lesser than 0
Where :
vx = in.nextInt(); // x speed of your pod
vy = in.nextInt(); // y speed of your pod
int ux = nextCheckPointIdX - x;
int uy = nextCheckPointIdY - y;
Here is the formula :
double cos = (vx*ux + vy*uy) / ( Math.sqrt(Math.pow(vx, 2) + Math.pow(vy, 2)) + Math.sqrt(Math.pow(ux, 2) + Math.pow(uy, 2)) );
Do you find any errors in the previous line ?
The denominator was having the problem.
int num = (vx*ux + vy*uy);
double den = (Math.sqrt(Math.pow(vx, 2) + Math.pow(vy, 2)) * (Math.sqrt(Math.pow(ux, 2) + Math.pow(uy, 2))) );
double cos = num / den;
System.out.println(cos);
System.out.println(Math.acos(cos));
In order to emulate Excel's rate function, I'm using the Apache POI rate function I grabbed from the svn:
private double calculateRate(double nper, double pmt, double pv, double fv, double type, double guess) {
//FROM MS http://office.microsoft.com/en-us/excel-help/rate-HP005209232.aspx
int FINANCIAL_MAX_ITERATIONS = 20; //Bet accuracy with 128
double FINANCIAL_PRECISION = 0.0000001; //1.0e-8
double y, y0, y1, x0, x1 = 0, f = 0, i = 0;
double rate = guess;
if (Math.abs(rate) < FINANCIAL_PRECISION) {
y = pv * (1 + nper * rate) + pmt * (1 + rate * type) * nper + fv;
}
else {
f = Math.exp(nper * Math.log(1 + rate));
y = pv * f + pmt * (1 / rate + type) * (f - 1) + fv;
}
y0 = pv + pmt * nper + fv;
y1 = pv * f + pmt * (1 / rate + type) * (f - 1) + fv;
// Find root by the Newton secant method
i = x0 = 0.0;
x1 = rate;
while ((Math.abs(y0 - y1) > FINANCIAL_PRECISION) && (i < FINANCIAL_MAX_ITERATIONS)) {
rate = (y1 * x0 - y0 * x1) / (y1 - y0);
x0 = x1;
x1 = rate;
if (Math.abs(rate) < FINANCIAL_PRECISION) {
y = pv * (1 + nper * rate) + pmt * (1 + rate * type) * nper + fv;
}
else {
f = Math.exp(nper * Math.log(1 + rate));
y = pv * f + pmt * (1 / rate + type) * (f - 1) + fv;
}
y0 = y1;
y1 = y;
++i;
}
return rate;
}
For calculateRate(120, 28.1, -2400, 0, 0, 0.1)), the output is the same as Excel: 0.599
But if I try the same calculation, this time with the values:
calculateRate(360, 15.9, -2400, 0, 0, 0.1))
In Excel I get 0.580, and the program returns -1.1500428517726355. Any hints?
There are a bunch of things that are wrong with this code that you have pasted in your question.
It assumes that a rate is always found (not true) and makes no provision for instances when a rate is not found.
Some of the statements will throw an error which could have been avoided by using a more appropriate programming statement. For instance, take the following statement from your code:
f = Math.exp(nper * Math.log(1 + rate));
This will throw an error when attempting to find Log of a negative or zero value. It could have been rewritten as
f = Math.pow(1 + rate, nper);
The comment in iterative calculations states that it is programming the secant method, yet the iterative calculations are checked for convergence of the wrong variable. It is testing for convergence of a future value when it should be testing for convergence of the interest rate.
I copy pasted your code in Notepad and removed the variable declaration of Java and replaced these with JavaScript variable declarations to test the code with your sample data. And just as I said, the code stops at the second iteration since the difference of future values goes out of error bound and since there is no test in place to see whether a rate is found, the code returns the interest rate as is and one which is wrong.
I am not sure why this code works in instances where it does report a correct rate as is the case with first data set. I would suggest re-coding of the function in a correct manner.
public double rate(double nper, double pmt, double pv)
{
//System.out.println("function rate : " + nper + " " + pmt + " pv " + pv);
double error = 0.0000001;
double high = 1.00;
double low = 0.00;
double rate = (2.0 * (nper * pmt - pv)) / (pv * nper);
while(true) {
// Check for error margin
double calc = Math.pow(1 + rate, nper);
calc = (rate * calc) / (calc - 1.0);
calc -= pmt / pv;
if (calc > error) {
// Guess is too high, lower the guess
high = rate;
rate = (high + low) / 2;
}
else if (calc < -error) {
// Guess is too low, higher the guess.
low = rate;
rate = (high + low) / 2;
}
else {
// Acceptable guess
break;
}
}
//System.out.println("Rate : " + rate);
return rate;
}
Example: =RATE(60, 2112500, 65000000) returns 0.025198; the same with Excel (correct).
Goal... Given a Zip code and a number of miles... get all zip codes within N miles.
Found one utility here in .NET: http://www.codeproject.com/Articles/9198/ZIP-Code-Utility
Found another utility in PHP.
Also found this: http://api.geonames.org/findNearbyPostalCodes?postalcode=53714&country=USA&radius=50&username=demo
Is there such a client in java?
UPDATE: I couldn't find one and no one responded, so I went ahead and created one.
I went ahead and wrote one.
package ndd;
public class RadiusBox {
static final Double kEarthRadiusMiles = 3956.0;
public static RadiusBox create(Double latitude, Double longitude, Double radiusInMiles)
{
/*
A point {lat,lon} is a distance d out on the tc radial from point 1 if:
lat = asin (sin (lat1) * cos (d) + cos (lat1) * sin (d) * cos (tc))
dlon = atan2 (sin (tc) * sin (d) * cos (lat1), cos (d) - sin (lat1) * sin (lat))
lon = mod (lon1 + dlon + pi, 2 * pi) - pi
Where:
* d is the distance in radians (an arc), so the desired radius divided by
the radius of the Earth.
* tc = 0 is N, tc = pi is S, tc = pi/2 is E, tc = 3*pi/2 is W.
*/
double lat;
double dlon;
double dLatInRads = latitude * (Math.PI / 180.0);
double dLongInRads = longitude * (Math.PI / 180.0);
double dDistInRad = radiusInMiles / kEarthRadiusMiles;
RadiusBox box = new RadiusBox ();
box.setRadius(radiusInMiles);
// N (tc == 0):
// lat = asin (sin(lat1)*cos(d) + cos(lat1)*sin(d))
// = asin (sin(lat1 + d))
// = lat1 + d
// Unused:
// lon = lon1, because north-south lines follow lines of longitude.
box.setTopLine((dLatInRads + dDistInRad) * (180.0 / Math.PI));
// S (tc == pi):
// lat = asin (sin(lat1)*cos(d) - cos(lat1)*sin(d))
// = asin (sin(lat1 - d))
// = lat1 - d
// Unused:
// lon = lon1, because north-south lines follow lines of longitude.
box.setBottomLine((dLatInRads - dDistInRad) * (180.0 / Math.PI));
// E (tc == pi/2):
// lat = asin (sin(lat1)*cos(d))
// dlon = atan2 (sin(tc)*sin(d)*cos(lat1), cos(d) - sin(lat1)*sin(lat))
// lon = mod (lon1 + dlon + pi, 2*pi) - pi
lat = Math.asin (Math.sin(dLatInRads) * Math.cos (dDistInRad));
dlon = Math.atan2 (Math.sin(Math.PI / 2.0) * Math.sin (dDistInRad) * Math.cos (dLatInRads), Math.cos (dDistInRad) - Math.sin (dLatInRads)* Math.sin (lat));
box.setRightLine( (((dLongInRads + dlon + Math.PI) % (2.0 * Math.PI)) - Math.PI) * (180.0 / Math.PI));
// W (tc == 3*pi/2):
// lat = asin (sin(lat1)*cos(d))
// dlon = atan2 (sin(tc)*sin(d)*cos(lat1), cos(d) - sin(lat1)*sin(lat))
// lon = mod (lon1 + dlon + pi, 2*pi) - pi
dlon = Math.atan2 (Math.sin (3.0 * Math.PI / 2.0) * Math.sin (dDistInRad) * Math.cos (dLatInRads), Math.cos (dDistInRad) - Math.sin (dLatInRads)* Math.sin (lat));
box.setLeftLine((((dLongInRads + dlon + Math.PI) % (2.0 * Math.PI)) - Math.PI) * (180.0 / Math.PI));
return box;
}
private double bottomLine;
private double topLine;
private double leftLine;
private double rightLine;
private double radius;
public double getBottomLine() {
return bottomLine;
}
public void setBottomLine(double bottomLine) {
this.bottomLine = bottomLine;
}
public double getTopLine() {
return topLine;
}
public void setTopLine(double topLine) {
this.topLine = topLine;
}
public double getLeftLine() {
return leftLine;
}
public void setLeftLine(double leftLine) {
this.leftLine = leftLine;
}
public double getRightLine() {
return rightLine;
}
public void setRightLine(double rightLine) {
this.rightLine = rightLine;
}
public double getRadius() {
return radius;
}
public void setRadius(double radius) {
this.radius = radius;
}
#Override
public String toString() {
return "RadiusBox [bottomLine=" + bottomLine + ", leftLine=" + leftLine
+ ", radius=" + radius + ", rightLine=" + rightLine
+ ", topLine=" + topLine + "]";
}
public String getSqlQuery() {
StringBuilder sb = new StringBuilder();
sb.append ("SELECT * FROM ZIP_CODES WHERE ");
sb.append ("LATITUDE >= ");
sb.append(bottomLine);
sb.append (" AND LATITUDE <= ");
sb.append(topLine);
sb.append (" AND LONGITUDE >= ");
sb.append(leftLine);
sb.append (" AND LONGITUDE <= ");
sb.append(rightLine);
sb.append (" ORDER BY CITY, STATE, ZIP");
return sb.toString();
}
}