public static HashMap<String, Double> toOrbitalElements(Vector3D r, Vector3D v, Body primary) {
		// Find orbital elements given position and velocity. The whole body is
		// given as input to adjust for parent bodies. Angles in radians.

		double grav = primary.mass * G;

		double rMag = r.magnitude();
		double vMag = v.magnitude();
		double rDotV = Vector3D.dotProduct(r, v);
		double twoPi = 2 * Math.PI;

		// Find specific angular momentum
		Vector3D h = Vector3D.crossProduct(r, v);

		// Find the node vector
		Vector3D k = new Vector3D(0, 0, 1);
		Vector3D n = Vector3D.crossProduct(k, h);
		double nMag = n.magnitude();

		Vector3D e = ((r.clone().multiply(vMag * vMag - (grav / rMag)))
				.subtract(v.clone().multiply(rDotV))).multiply(1 / grav);
		double eMag = e.magnitude();

		double sguig = vMag * vMag / 2 - grav / rMag;

		// Not true if e = 1
		double a = -grav / (2 * sguig);
		double p = a * (1 - eMag * eMag);

		double i = Math.acos(h.z / h.magnitude());

		double node = Math.acos(n.x / nMag);
		if (n.y < 0) {
			node = twoPi - node;
		}

		double peri = Math.acos(Vector3D.dotProduct(n, e) / (nMag * eMag));
		if (e.z < 0) {
			peri = twoPi - peri;
		}

		double anomaly = Math.acos(Vector3D.dotProduct(e, r) / (eMag * rMag));
		if (rDotV < 0) {
			anomaly = twoPi - anomaly;
		}

		HashMap<String, Double> orb = new HashMap<String, Double>();
		orb.put("p", p);
		orb.put("a", a);
		orb.put("e", eMag);
		orb.put("i", i);
		orb.put("node", node);
		orb.put("peri", peri);
		orb.put("v", anomaly);

		return orb;
	}