public void calculatePosition() {
		double sigma1, tsig1, tu1, sa, ca, sa1, ca1, A, B, twosm;
		double cu1, su1, uu;
		double sigma;
		int nIters = 0, nMaxIters = 10;
		double c2sm, ssig, csig, dsig = 0.0, lastdsig;
		double lambda, C;
		double x, y;

		double a = ellipsoid.getSemiMajorAxis();
		double f = ellipsoid.getFlattening();

		double b = a * (1.0 - f);

		if (!havePositionA)
			throw new IllegalStateException("positionA is not defined");

		if (!haveAzimuthA)
			throw new IllegalStateException("azimuthA is not defined");

		if (!haveDistance)
			throw new IllegalStateException("distance is not defined");

		tu1 = (1.0 - f) * Math.tan(latitudeA);
		cu1 = Math.cos(Math.atan(tu1));
		su1 = Math.sin(Math.atan(tu1));

		ca1 = Math.cos(azimuthA);
		sa1 = Math.sin(azimuthA);

		tsig1 = tu1 / ca1;
		sa = cu1 * sa1;
		ca = 1.0 - sa * sa;

		uu = (1.0 - sa * sa) * (a * a - b * b) / (b * b);

		A = 1.0 + (uu / 16384.0)
				* (4096.0 + uu * (-768.0 + uu * (320.0 - 175.0 * uu)));

		B = (uu / 1024.0) * (256.0 + uu * (-128.0 + uu * (74.0 - 47.0 * uu)));

		sigma1 = Math.atan(tsig1);
		if (tsig1 < 0.0)
			sigma1 += Math.PI;

		sigma = geodesicDistance / (b * A);

		lastdsig = 0.0;

		twosm = 2.0 * sigma1 + sigma;

		do {
			lastdsig = dsig;

			c2sm = Math.cos(twosm);
			ssig = Math.sin(sigma);
			csig = Math.cos(sigma);

			dsig = B
					* ssig
					* (c2sm + (B / 4.0)
							* (csig * (-1.0 + 2.0 * c2sm * c2sm) - (B / 6.0)
									* c2sm * (-3.0 + 4.0 * ssig * ssig)
									* (-3.0 + 4.0 * c2sm * c2sm)));

			sigma = geodesicDistance / (b * A) + dsig;

			twosm = 2 * sigma1 + sigma;

			nIters += 1;
		} while ((Math.abs(dsig - lastdsig) > EPSILON) && (nIters <= nMaxIters));

		if (nIters > nMaxIters)
			throw new ArithmeticException("Exceeded iteration limit");

		c2sm = Math.cos(twosm);
		ssig = Math.sin(sigma);
		csig = Math.cos(sigma);

		y = su1 * csig + cu1 * ssig * ca1;

		x = su1 * ssig - cu1 * csig * ca1;
		x *= x;
		x += sa * sa;
		x = (1.0 - f) * Math.sqrt(x);

		latitudeB = Math.atan2(y, x);

		y = ssig * sa1;
		x = cu1 * csig - su1 * ssig * ca1;

		lambda = Math.atan2(y, x);

		C = (f / 16.0) * ca * (4.0 + f * (4.0 - 3.0 * ca));

		x = (1.0 - C)
				* f
				* sa
				* (sigma + C * ssig
						* (c2sm + (C * csig * (-1.0 + 2.0 * c2sm * c2sm))));

		lambda -= x;

		longitudeB = longitudeA + lambda;

		havePositionB = true;

		y = sa;

		x = -su1 * ssig + cu1 * csig * ca1;

		azimuthB = Math.atan2(-y, -x);
		haveAzimuthB = true;
	}