I have this code:
void drawCircle(int x, int y, int r, int color) {
double PI = 3.1415926535;
double i, angle, x1, y1;
for (i = 0; i < 360; i += 1) {
angle = i;
x1 = r * cos(angle * PI / 180);
y1 = r * sin(angle * PI / 180);
int ElX = (int) (x + x1);
int ElY = (int) (y + y1);
myPixelElements[ElX][ElY].setElementColor(color);
}
}
It almost works but for some reason it draws 2 dots wrong:
cos and sin functions produce double values from -1 to +1, and when you cast double to int like this: int ElX = (int) (x + x1), some data will be inevitably lost, because such cast just chops the decimal part away. Instead, I suggest rounding double with Math.round, check example below:
System.out.println((int) 0.99); // 0
System.out.println((int) -0.99); // 0
System.out.println(Math.round(0.99)); // 1
System.out.println(Math.round(-0.99)); // -1
Note that Math.round returns long, so it still must be casted to int:
int ElX = (int) Math.round(x + x1);
int ElY = (int) Math.round(y + y1);
Output
Before After
****** *****
* * *** ***
* * * *
* * ** **
* * * *
* ** * *
* * * *
* * ** **
* * * *
****** *** ***
* *****
You're doing integer division in these lines:
x1 = r * cos(angle * PI / 180);
y1 = r * sin(angle * PI / 180);
A couple things are going on here. First, the integer division issue (change 180 to 180.0 to get a quick fix there). Second, you're doing the whole PI / 180.0 calculation every time through the loop - try pulling it out into its own variable:
double degToRadFactor = 3.1415926535 / 180.0
// ...
x1 = r * cos(angle * degToRadFactor)
y1 = r * sin(angle * degToRadFactor)
Related
I am currently on spring break and since I only work 25 hours a week I have too much free time on my hands. I am a Computer Science student and I decided to spend my free time improving my coding skills and my understanding of electromagnetic physics by creating a very simple calculator that is used to solve Coulomb's law with vectors which are used to solve the force between any two charged particles in a system of charged particles.
Now I have a somewhat accurate calculator working, I still have a few minor inaccuracies that I need to address but the code can be found down below, but it still works enough for the next step I would like to achieve.
This next step for me is to create a GUI and an interactive graph for the users to see. I say interactive because my ideal program would give the user the ability to drag and drop points on the canvas all the while the program is calculating the force vectors and net force that is present between the points the user places on the space. I would also be satisfied with just being able to draw the graph given the charges and XY-coordinates as well.
My question is does anyone know of any good tutorials or respectable libraries that I can look into to achieve either of these two ideas? I have a strong background in Java so I would prefer this to be done in Java, but I am never one to step away from learning a new language when I need too.
Code:
Charge.java
package objects;
/**
* Charge is an object used to represent an arbitrarily charged particle in some
* XY-plane. This class will store the value of the charge, the XY-coordinates
* of that charge's location, and functions to access these values.
*
* #author Seth
*
*/
public class Charge {
private double q; // the charge of the particle in Coulombs
private double x; // the location along the x-axis of the charge
private double y; // the location along the y-axis of the charge
public Charge(double x, double y, double q) {
this.x = x;
this.y = y;
this.q = q;
}
/**
* public method to get q
*
* #return
* double - value of the Charge object
*/
public double getQ() {
if (this != null)
return q;
else
return 0;
}
/**
* public method to get x
*
* #return
* double - value of the x coordinate
*/
public double getX() {
if (this != null)
return x;
else
return 0;
}
/**
* public method to get y
*
* #return
* double - value of the y coordinate
*/
public double getY() {
if (this != null)
return y;
else
return 0;
}
}
ElectricForceCalculator.java
package objects;
/**
* ElectricForceCalculator is a class that has the ability to solve the net
* force between two charged particles in a xy-plane
*
* #author Seth
*
*/
public class ElectricForceCalculator {
/**
* Private method used to find the force between two charges
*
* #param Q
* Charge - The charged we are focused on
* #param q
* Charge - The second charge effecting Q
* #return double array - the force vectors found where i = 0 is the x
* direction and i = 1 is the y direction
*/
private double[] calcForceHelper(Charge Q, Charge q) {
double radius, quanOfCharge;
double[] radiusVector = new double[2], forceVector = new double[2];
double x1 = Q.getX(), y1 = Q.getY();
double x2 = q.getX(), y2 = q.getY();
double q1 = Q.getQ(), q2 = q.getQ();
System.out.print("Calculating radius of Q and q...\n\t");
radius = calcRadius(x1, x2, y1, y2);
System.out.print("Calculating radiusVector of Q and q...\n\t");
radiusVector = calcRadiusVector(x1, x2, y1, y2, radius);
System.out.print("Calculating quantityOfCharge of Q and q...\n\t");
quanOfCharge = calcCharge(q1, q2, radius);
System.out.print("Calculating Force Vector of Q and q...\n\t");
forceVector = calcForceVector(radius, radiusVector, quanOfCharge);
return forceVector;
}
/**
* Public method used to find the overall net force of a system of charged
* particles
*
* #param Q
* Charge - the Charge object we are focused on
* #param q
* Charge array - the list of all the other Charge object
* effecting Q
* #param numCharges
* int - the number of indices found in the list of Charge
* objects q
* #return double - value of the net force experienced by Charge object Q
*/
public double calcForce(Charge Q, Charge[] q, int numCharges) {
double result;
double[] sum = { 0.0, 0.0 }, tempSum = new double[2];
for (int i = 0; i < numCharges - 1; i++) {
tempSum = calcForceHelper(Q, q[i]); // Help with readability to call
// method helper
fixSigns(Q, q[i], tempSum);
sum[0] += tempSum[0];
sum[1] += tempSum[1];
}
System.out.println("\nOverall force Vector on Q = (" + sum[0] + ")x + (" + sum[1] + ")y.");
result = Math.pow(sum[0], 2) + Math.pow(sum[1], 2);
result = Math.sqrt(result);
double theta = calcTheta(sum);
System.out.print("Force on charge Q by all other charges = " + result + " at ");
if (sum[1] > 0) {
if (sum[0] > 0)
System.out.print((float) Math.round(90 - theta) + " degrees.");
else
System.out.print((float) Math.round(180 - theta) + " degrees.");
} else {
if (sum[0] > 0)
System.out.print((float) Math.round(180 + theta) + " degrees.");
else
System.out.print((float) Math.round(270 + theta) + " degrees.");
}
return result;
}
/**
* Method used to assign negative values to any forces that should be
* negative
*
* #param Q
* Charge - the charge we are focused on
* #param q
* charge - the charge effecting Q
* #param tempSum
* the force vectors we are fixing, if needed
*/
private void fixSigns(Charge Q, Charge q, double[] tempSum) {
if (Q.getQ() < 0 && q.getQ() < 0) {
if (q.getX() > Q.getX())
tempSum[0] *= -1;
if (q.getY() > Q.getY())
tempSum[1] *= -1;
} else if (Q.getQ() > 0 && q.getQ() > 0) {
if (q.getX() > Q.getX())
tempSum[0] *= -1;
if (q.getY() > Q.getY())
tempSum[1] *= -1;
} else {
if (q.getX() < Q.getX())
tempSum[0] *= -1;
if (q.getY() < Q.getY())
tempSum[1] *= -1;
}
}
/**
* Private method used to calculate the angle Theta between two vectors
*
* #param forceVector
* double array - the force vectors we are finding the angle
* between
* #return double - the angle between the two force vectors given
*/
private double calcTheta(double[] vectors) {
double result = Math.abs(vectors[1]) / Math.abs(vectors[0]);// finds
// angle
// between 0
// and 90
result = Math.toDegrees(Math.atan(result));
return result;
}
/**
* Private method used to calculate the force vectors experienced by a
* charged particle
*
* #param radius
* double - distance between two charges
* #param radiusVector
* double array - the radius vectors between two charges
* #param quanOfCharge
* double - the quantity of charge given by k(coulomb's constant)
* * charge of Q * charge of q
* #return double array - the force vectors experienced by two charges
*/
private double[] calcForceVector(double radius, double[] radiusVector, double quanOfCharge) {
double[] result = new double[2];
double theta = calcTheta(radiusVector), magnitude = quanOfCharge;
result[0] = magnitude * Math.cos(Math.toRadians(theta));
result[1] = magnitude * Math.sin(Math.toRadians(theta));
System.out.print("Force Vector = (" + result[0] + ")x + (" + result[1] + ")y.\n");
return result;
}
/**
* private method used to calculate the quantity of charge between two
* charged particles(k * charge of Q * charge of q)
*
* #param Q
* double - the charge in Coulombs of the Charge object Q
* #param q
* double - the charge in Coulombs of the Charge object q
* #return double - the quantity of charge
*/
private double calcCharge(double Q, double q, double d) {
double result;
result = (((Q * q) / (d * d)) * 9E9);
result = Math.abs(result);
System.out.print("Quantity of charge(Q*q*k) = " + result + "\n");
return result;
}
/**
* Private method used to calculate the radius vector between two points on
* a xy-plane
*
* #param x1
* double - x coordinate of the Charge object Q
* #param x2
* double - y coordinate of the Charge object q
* #param y1
* double - x coordinate of the Charge object Q
* #param y2
* double - y coordinate of the Charge object q
* #param radius
* double - distance between the two points
* #return double array - the distance vectors between two charges
*/
private static double[] calcRadiusVector(double x1, double x2, double y1, double y2, double radius) {
double[] result = new double[2];
result[0] = (x2 - x1) / radius;
result[1] = (y2 - y1) / radius;
result[0] = Math.abs(result[0]);
result[1] = Math.abs(result[1]);
System.out.print("Radius vector = (" + result[0] + ")x + (" + result[1] + ")y\n");
return result;
}
/**
* Private method used to calculate the distance between two points on a
* xy-plane using the distance formula or [(x2-x1)+(y2-y1]^(1/2)
*
* #param x1
* double - x coordinate of the Charge object Q
* #param x2
* double - y coordinate of the Charge object q
* #param y1
* double - x coordinate of the Charge object Q
* #param y2
* double - y coordinate of the Charge object q
* #return double - distance between the two points given
*/
private double calcRadius(double x1, double x2, double y1, double y2) {
double distance = Math.pow((x2 - x1), 2) + Math.pow((y2 - y1), 2);
distance = Math.sqrt(distance);
System.out.print("Radius = " + distance + "\n");
return distance;
}
/**
* Main
*
* #param args
*/
public static void main(String[] args) {
Charge Q = new Charge(-.02, .015, -4E-6);
Charge[] q = new Charge[2];
q[0] = new Charge(.035, .005, 3E-6);
q[1] = new Charge(-.0837, .0262, 4E-6);
ElectricForceCalculator calc = new ElectricForceCalculator();
calc.calcForce(Q, q, 3);
}
}
Sample output:
charge Q is -4.0E-6 C at (x,y) = (-0.02, 0.015).
charge q1 is 3.0E-6 C at (x,y) = (0.035, 0.005).
charge q1 is 4.0E-6 C at (x,y) = (-0.0837, 0.0262).
Calculating radius of Q and q...
Radius = 0.05590169943749475
Calculating radiusVector of Q and q...
Radius vector = (0.9838699100999075)x + (0.17888543819998312)y
Calculating quantityOfCharge of Q and q...
Quantity of charge(Q*q*k) = 34.559999999999995
Calculating Force Vector of Q and q...
Force Vector = (34.0025440930528)x + (6.182280744191415)y.
Calculating radius of Q and q...
Radius = 0.06467712114805357
Calculating radiusVector of Q and q...
Radius vector = (0.984892321570454)x + (0.17316788071568426)y
Calculating quantityOfCharge of Q and q...
Quantity of charge(Q*q*k) = 34.4239839545986
Calculating Force Vector of Q and q...
Force Vector = (33.903917474748674)x + (5.96112834720856)y.
Overall force Vector on Q = (0.09862661830412378)x + (-0.2211523969828546)y.
Force on charge Q by all other charges = 0.24214787327038295
I gone thouth the url https://math.stackexchange.com/questions/361412/finding-the-angle-between-three-points
and wrote a simple code as follows. Not sure how can I test it.
double x1 = 2, x2 = 3, x3= 4;
double y1 = 200, y2 = 215, y3= 225;
double l1x = x2 - x1;
double l1y = y2 - y1;
double l1xSQR = l1x * l1x;
double l1ySQR = l1y * l1y;
double l1SQRT = Math.sqrt(l1xSQR + l1ySQR);
double l2x = x3 - x2;
double l2y = y3 - y2;
double l2xSQR = l2x * l2x;
double l2ySQR = l2y * l2y;
double l2SQRT = Math.sqrt(l2xSQR + l2ySQR);
System.out.println(Math.abs(Math.cos(((l1x * l2x) + (l1y * l2y))/(l1SQRT*l2SQRT))));
Is this correct way to find the angle between 3 point in 2D.
The expression
((l1x * l2x) + (l1y * l2y))/(l1SQRT*l2SQRT)
is already the cosine of the desired angle, so you should write
Math.acos(((l1x * l2x) + (l1y * l2y))/(l1SQRT*l2SQRT))
to get the angle in radians. Or
Math.acos(((l1x * l2x) + (l1y * l2y))/(l1SQRT*l2SQRT)) * 180.0 / Math.PI
if you need it in degrees.
Can be better as regards accuracy and generality to use
atan2(D20x * D10y - D20y * D10x, D20x * D10x + D20y * D10y).
Also
atan2(D20y, D20x) - atan2(D10y, D10x),
which takes two atan calls.
I am almost new to Java programming. I want to implement the following code in MATSim (it is a simulation programme for urban planning purposes). This code is about converting WGS84 (longitude and latitude) to OSGB36 (British National Grid).
https://gist.github.com/schoenobates/3497544#file-osgb-java
The MATSim library has an interface (below) to put the conversion codes in it and use it for visual simulation.
I have already tried many times to deal with errors, but it doesn't work me. Would you please give me some ideas about how I can do this.
package org.matsim.core.utils.geometry;
import org.matsim.api.core.v01.Coord;
/**
* A simple interface to convert coordinates from one coordinate system to
* another one.
*
* #author mrieser
*/
public interface CoordinateTransformation {
/**
* Transforms the given coordinate from one coordinate system to the other.
*
* #param coord The coordinate to transform.
* #return The transformed coordinate.
*/
public Coord transform(Coord coord);
}
Thank you, Somayeh
Ok, the error are here:
I did the below:
It is giving me two syntax errors:
double[] eastANDnorth(double lat, double lon) { for curly parenthesis and comma;
and
return new double(OSGB36N, OSGB36E); for double
package org.matsim.core.utils.geometry.transformations;
import org.matsim.api.core.v01.Coord;
import org.matsim.core.utils.geometry.CoordImpl;
import org.matsim.core.utils.geometry.CoordinateTransformation;
public class WGS84toOSGB36 implements CoordinateTransformation {
#Override
public Coord transform(Coord coord) {
// WGS84 ELLIPSOID
double WGS84_A = 6378137;
double WGS84_B = 6356752.314245;
double WGS84_E2 = ((WGS84_A * WGS84_A) - (WGS84_B * WGS84_B) / (WGS84_A * WGS84_A));
// NstGrid scale factor on central meridian
final double F0 = 0.9996012717;
// Airy 1830 major & minor semi-axes - note .909 not .910
final double AIRY_A = 6377563.396;
final double AIRY_B = 6356256.909;
// NatGrid true origin
final double LAT0 = Math.toRadians(49); //Phi0
final double LON0 = Math.toRadians(-2); //Lamda0
// northing & easting of true origin, metres
final double N0 = -100000;
final double E0 = 400000;
// eccentricity squared
final double E2 = ((AIRY_A * AIRY_A) - (AIRY_B * AIRY_B)) / (AIRY_A *AIRY_A);
final double N = (AIRY_A - AIRY_B) / (AIRY_A + AIRY_B);
final double N2 = N * N;
final double N3 = N * N * N;
final double TX = -446.448;
final double TY = 125.157;
final double TZ = -542.060;
final double RX = Math.toRadians(-0.1502 / 3600);
final double RY = Math.toRadians(-0.2470 / 3600);
final double RZ = Math.toRadians(-0.8421 / 3600);
final double S = 20.4894 / 1e6 + 1;
/*----*/double[] eastANDnorth(double lat, double lon) {/* error in this line */
// -- 1: convert polar to cartesian coordinates (using ellipse 1)
// WGS84 ellipsoid
double sinPhi = Math.sin(lat);
double cosPhi = Math.cos(lat);
double sinLambda = Math.sin(lon);
double cosLambda = Math.cos(lon);
double H = 24.7; // for the moment
double nu = WGS84_A / Math.sqrt(1 - WGS84_E2 * sinPhi * sinPhi);
double x1 = (nu + H) * cosPhi * cosLambda;
double y1 = (nu + H) * cosPhi * sinLambda;
double z1 = ((1-WGS84_E2) * nu + H) * sinPhi;
// -- 2: apply helmert transform using appropriate params
double x2 = TX + x1 * S - y1 * RZ + z1 * RY;
double y2 = TY + x1 * RZ + y1 * S - z1 * RX;
double z2 = TZ - x1 * RY + y1 * RX + z1 * S;
// -- 3: convert cartesian to polar coordinates (using ellipse 2)
double precision = 4 / AIRY_A;
double p = Math.sqrt(x2 * x2 + y2 * y2);
double phi = Math.atan2(z2, p * (1 - E2)), phiP = 2 * Math.PI;
while (Math.abs(phi - phiP) > precision) {
nu = AIRY_A / Math.sqrt(1 - E2 * Math.sin(phi) * Math.sin(phi));
phiP = phi;
phi = Math.atan2(z2 + E2 * nu * Math.sin(phi), p);
}
double lambda = Math.atan2(y2, x2);
// -- 4: now we're in OSGB, get the EN coords
double cosLat = Math.cos(phi), sinLat = Math.sin(phi);
nu = AIRY_A * F0 / Math.sqrt(1 - E2 * sinLat * sinLat);
double rho = AIRY_A * F0 * (1 - E2) / Math.pow(1 - E2 * sinLat * sinLat, 1.5);
double eta2 = nu / rho - 1;
double Ma = (1 + N + (5 / 4) * N2 + (5 / 4) * N3) * (phi - LAT0);
double Mb = (3 * N + 3 * N * N + (21 / 8) * N3) * Math.sin(phi - LAT0) * Math.cos(phi + LAT0);
double Mc = ((15 / 8) * N2 + (15 / 8) * N3) * Math.sin(2 * (phi - LAT0)) * Math.cos(2 * (phi + LAT0));
double Md = (35 / 24) * N3 * Math.sin(3 * (phi - LAT0)) * Math.cos(3 * (phi + LAT0));
double M = AIRY_B * F0 * (Ma - Mb + Mc - Md); // meridional arc
double cos3lat = cosLat * cosLat * cosLat;
double cos5lat = cos3lat * cosLat * cosLat;
double tan2lat = Math.tan(phi) * Math.tan(phi);
double tan4lat = tan2lat * tan2lat;
double I = M + N0;
double II = (nu / 2) * sinLat * cosLat;
double III = (nu / 24) * sinLat * cos3lat * (5 - tan2lat + 9 * eta2);
double IIIA = (nu / 720) * sinLat * cos5lat * (61 - 58 * tan2lat + tan4lat);
double IV = nu * cosLat;
double V = (nu / 6) * cos3lat * (nu / rho - tan2lat);
double VI = (nu / 120) * cos5lat * (5 - 18 * tan2lat + tan4lat + 14 * eta2 - 58 * tan2lat * eta2);
double dLon = lambda - LON0;
double dLon2 = dLon * dLon, dLon3 = dLon2 * dLon, dLon4 = dLon3 * dLon, dLon5 = dLon4 * dLon, dLon6 = dLon5 * dLon;
double OSGB36N = I + II * dLon2 + III * dLon4 + IIIA * dLon6;
double OSGB36E = E0 + IV * dLon + V * dLon3 + VI * dLon5;
/*--------*/return new double(OSGB36N, OSGB36E);/* error in this line */
}
return new CoordImpl(OSGB36N, OSGB36E);
}
}
You are trying to create a array with this expression:
new double(OSGB36N, OSGB36E)
However that's invalid java syntax. You should change it to
new double[]{ OSGB36N, OSGB36E }
Also your're trying to declare a method inside another method, i.e. eastANDnorth inside transform, which is not valid in java.
I am trying to randmly create set of points with random position of an initial point.
Unfortunatly almost all of my generated points are located in upper left corner. Is there a mistake in my calculations?
private void makePath() {
int r = 25;
Random rand = new Random();
double angle = Math.toRadians(rand.nextInt(361));
int nx = (int) (x + r * Math.cos(angle));
int ny = (int) (y - r * Math.sin(angle));
path.add(new Point2D(nx, ny));
}
For the values, try using:
int nx = (int) (x + r * Math.cos(angle));
int ny = (int) (y + r * Math.sin(angle));
Using y + r * ... instead. This is coming from a method I wrote to do the exact same thing:
/**
* Generates a new point within a circular radius from
* the given <tt>x</tt> and <tt>y</tt> coordinates. This
* is done by generating a random offset along the
* horizontal axis, then applying a rotation.
*
* #param seed The seed to generate the point from.
* #param x The x coordinate of the center of the
* circle.
* #param y The y coordinate of the center of the
* circle.
* #return The newly generated point, within the
* specified radius of the point <tt>(x, y)
* </tt>.
* #see ClusterGenerator#RADIUS
*/
private static Point makePoint(final Random seed, final int x, final int y) {
final int offset = seed.nextInt(RADIUS);
final double rotation = 2 * Math.PI * Math.random();
final int x1 = (int) (Math.sin(rotation) * offset);
final int y1 = (int) (Math.cos(rotation) * offset);
return new Point(x + x1, y + y1);
}
I need to find a bounding box given 4 lat/long points and a bearing (as seen in the example picture). I always know which two points are lined up by the bearing (1 and 2 in the example), so I will always know the length of the bounding box. The width however is arbitrary, with the points being anywhere along the lines (3 and 4 in the example).
My first thought is that I'll have to calculate the angles between the points (1 & 3, 1 & 4, 2 & 3, 2 & 4) and then use a series of "law of cosine" equations to calculate the corner points. Is there a simpler way? Would that even work?
So looking around and even asking on probably a more appropriate site (here), I found a solution based on something by Chris Veness (here) to find the intersection point given two points and their bearings. So to get the corners of the bounding box I just take each combination of top/bottom and left/right (1 & 3, 1 & 4, 2 & 3, 2 & 4) and find the intersections using the known bearing and adjusting accordingly. For example to find the bottom right of the image I'd calculate the intersection of points 1 & 3 using the bearing + 90 for the direction of point 1 and the bearing - 180 for the direction of point 3.
I can take no credit for the algorithm or even really explain it in terms of how it works geometrically, but its worked in my testing. Below is my java translation from the javascript version provided by Chris
public static CoordD getIntersection(CoordD point1, double bearing1, CoordD point2, double bearning2) {
double lat1 = rad(point1.latitude); double lon1 = rad(point1.longitude);
double lat2 = rad(point2.latitude); double lon2 = rad(point2.longitude);
double bearing13 = rad(bearing1); double bearing 23 = rad(bearing2);
double dLat = lat2 - lat1; double dLon = lon2 - lon1;
double dist12 = 2 * Math.asin( Math.sqrt( Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.cos(lat1) * Math.cos(lat2) * Math.sin(dLon / 2) * Math.sin(dLon / 2) ) );
if (dist12 == 0) return null;
double bearingA = Math.acos( ( Math.sin(lat2) - Math.sin(lat1) * Math.cos(dist12) ) /
( Math.sin(dist12) * Math.cos(lat1) ) );
double bearingB = Math.acos( ( Math.sin(lat1) - Math.sin(lat2) * Math.cos(dist12) ) /
( Math.sin(dist12) * Math.cos(lat2) ) );
if (Double.isNaN(bearingA)) bearingA = 0;
if (Double.isNaN(bearingB)) bearingB = 0;
double bearing12, bearing21;
if (Math.sin(dLon) > 0) {
bearing12 = bearingA;
bearing21 = 2 * Math.PI - bearingB;
} else {
bearing12 = 2 * Math.PI - bearingA;
bearing21 = bearingB;
}
double alpha1 = (bearing13 - bearing12 + Math.PI) % (2 * Math.PI) - Math.PI; // Angle 2-1-3
double alpha2 = (bearing21 - bearing23 + Math.PI) % (2 * Math.PI) - Math.PI; // Angle 1-2-3
if (Math.sin(alpha1) == 0 && Math.sin(alpha2) == 0) return null; // Infinite intersections
if (Math.sin(alpha1) * Math.sin(alpha2) < 0) return null; // Ambiguous intersection
// needed?
// alpha1 = Math.abs(alpha1);
// alpha2 = Math.abs(alpha2);
double alpha3 = Math.acos( -Math.cos(alpha1) * Math.cos(alpha2) +
Math.sin(alpha1) * Math.sin(alpha2) * Math.cos(dist12) );
double dist13 = Math.atan2( Math.sin(dist12) * Math.sin(alpha1) * Math.sin(alpha2),
Math.cos(alpha2) + Math.cos(alpha1) * Math.cos(alpha3) );
double lat3 = Math.asin( Math.sin(lat1) * Math.cos(dist13) +
Math.cos(lat1) * Math.sin(dist13) * Math.cos(bearing13) );
double dLon13 = Math.atan2( Math.sin(bearing13) * Math.sin(dist13) * Math.cos(lat1),
Math.cos(dist13) - Math.sin(lat1) * Math.sin(lat3) );
double lon3 = lon1 + dLon3;
lon3 = (lon3 + 3 * Math.PI) % ( 2* Math.PI) - Math.PI // normalize to +/-180
return new CoordD(deg(lat3), deg(lon3));
}
rad() and deg() are just helper functions that translate between radians and degrees. CoordD is a helper class that just contains two double to store a lat/long point.