public RotationQuaternion(Vector3D axis, double angle) { double sinCoeff = Math.Sin(angle / 2); this._r = Math.Cos(angle / 2); this._v = new Vector3D( axis.x() * sinCoeff, axis.y() * sinCoeff, axis.z() * sinCoeff); }
public KeplerOrbit(Vector3D r, Vector3D dr) { Vector3D h = r % dr; Vector3D ev = ((dr % h) / _GM) - (r / r.norm()); Vector3D n = new Vector3D(0, 0, 1) % h; double nu = 0; if (r * dr >= 0) { nu = Math.Acos((ev * r) / (ev.norm() * r.norm())); } else { nu = (2*Math.PI - Math.Acos((ev * r) / (ev.norm() * r.norm()))); } double E = Math.Acos((ev.norm() + Math.Cos(nu)) / (1 + (ev.norm() * Math.Cos(nu)))); double i = Math.Acos(h.z()/h.norm()); double e = ev.norm(); double Omega = 0; if (n.y() >= 0) { Omega = Math.Acos(n.x() / n.norm()); } else { Omega = 2*Math.PI - Math.Acos(n.x() / n.norm()); } double omega = 0; if (ev.z() >= 0) { omega = Math.Acos((n*ev) / (n.norm()*ev.norm())); } else { omega = 2*Math.PI - Math.Acos((n * ev) / (n.norm() * ev.norm())); } double M = E - (e * Math.Sin(E)); double a = 1 / ((2/r.norm()) - (Math.Pow(dr.norm(),2)/_GM)); this.setKeplerElements(a, e, omega, Omega, i, M); }
public Vector3D getPosition(double t) { double M = 0; double dt = 0; double E = 0; double nu = 0; double r_c = 0; Vector3D o = new Vector3D(); //Vector3D d_o = new Vector3D(); Vector3D r = new Vector3D(); if (t == this._epoch) { M = this._M0; } else { dt = 86400 * (t - this._epoch); M = this._M0 + dt * Math.Sqrt((_GM) / (Math.Pow(this._a, 3))); M = tools.normalizeAngle(M); } E = tools.solveKeplerForE(M, this._e); nu = 2 * Math.Atan2(Math.Sqrt(1 + this._e) * Math.Sin(E / 2), Math.Sqrt(1 - this._e) * Math.Cos(E / 2)); r_c = this._a * (1 - this._e * Math.Cos(E)); o = r_c * new Vector3D(Math.Cos(nu), Math.Sin(nu), 0); //d_o = (Math.Sqrt(_GM * this._a) / r_c) * new Vector3D(-Math.Sin(E), Math.Sqrt(1 - Math.Pow(this._e, 2)) * Math.Cos(E), 0); r = new Vector3D( o.x() * (Math.Cos(this._omega) * Math.Cos(this._Omega) - Math.Sin(this._omega) * Math.Cos(this._i) * Math.Sin(this._Omega)) - o.y() * (Math.Sin(this._omega) * Math.Cos(this._Omega) + Math.Cos(this._omega) * Math.Cos(this._i) * Math.Sin(this._Omega)), o.x() * (Math.Cos(this._omega) * Math.Sin(this._Omega) - Math.Sin(this._omega) * Math.Cos(this._i) * Math.Cos(this._Omega)) + o.y() * (Math.Cos(this._omega) * Math.Cos(this._i) * Math.Cos(this._Omega) - Math.Sin(this._omega) * Math.Sin(this._Omega)), o.x() * (Math.Sin(this._omega) * Math.Sin(this._i)) + o.y() * (Math.Cos(this._omega) * Math.Sin(this._i))); //Console.WriteLine(o.x().ToString("e")); //Console.WriteLine(o.y().ToString("e")); //Console.WriteLine(o.z().ToString("e")); return r; }
private PixelInformation getIlluminationDirectionPerRenderingPixel(SpacecraftState sc, uint x, uint y) { PixelInformation PixelOut = new PixelInformation(); Vector3D c_pos = sc.getPosition(); // STEP 1: Visibility Test Vector3D rayDirection = (sc.getPOVDirection() + (((1 + Convert.ToDouble(this._height) - (2 * Convert.ToDouble(y))) / (2 * Convert.ToDouble(this._height))) * sc.getPOVUp()) - (((1 + Convert.ToDouble(this._width) - (2 * Convert.ToDouble(x))) / (2 * Convert.ToDouble(this._width))) * sc.getPOVRight())).unit(); double discriminant = 4 * Math.Pow(c_pos * rayDirection, 2) - 4 * (rayDirection * rayDirection) * (c_pos * c_pos) + 4 * (rayDirection * rayDirection) * Math.Pow(_moon_radius, 2); bool encounter = false; Vector3D p_surf = new Vector3D(); if (discriminant < 0) { // no encounter } else if (discriminant == 0) { // one intersection encounter = true; double t = (-2 * (c_pos * rayDirection)) / (2 * (rayDirection * rayDirection)); p_surf = c_pos + rayDirection * t; } else { // two intersections encounter = true; double t1 = (-2 * (c_pos * rayDirection) + Math.Sqrt(discriminant)) / (2 * (rayDirection * rayDirection)); double t2 = (-2 * (c_pos * rayDirection) - Math.Sqrt(discriminant)) / (2 * (rayDirection * rayDirection)); Vector3D ray_point1 = c_pos + rayDirection * t1; Vector3D ray_point2 = c_pos + rayDirection * t2; double ray_norm1 = (ray_point1 - c_pos).norm(); double ray_norm2 = (ray_point2 - c_pos).norm(); if (ray_norm1 < ray_norm2) { p_surf = ray_point1; } else { p_surf = ray_point2; } } if (encounter) { /* Pixel shows the Moon's surface: Continue with executing steps 2 - 8. */ double x1 = Convert.ToDouble(x); double y1 = Convert.ToDouble(y); // STEP 2: Obtaining the Surface Hit Point PixelOut.lat = tools.rad2deg((Math.PI / 2) - Math.Acos(p_surf.z() / _moon_radius)); PixelOut.lon = tools.rad2deg(Math.Atan2(p_surf.y(), p_surf.x())); // STEP 3: Calculation of the Sun's direction Vector3D hat_p_surf = p_surf.unit(); Vector3D hat_d_sun = (sc.getSunPosition() - p_surf).unit(); // STEP 4: Derivation of the Local Tangent Plane of the Surface Hit Point (nothing to do here) // STEP 5: Determination of a Subsurface Point of the Solar Illumination Direction on the Local Tangent Plane double lambda_5 = -(1000 * (hat_d_sun.x() * hat_p_surf.x() + hat_d_sun.y() * hat_p_surf.y() + hat_d_sun.z() * hat_p_surf.z())) / (hat_p_surf.x() * hat_p_surf.x() + hat_p_surf.y() * hat_p_surf.y() + hat_p_surf.z() * hat_p_surf.z()); Vector3D p_local = p_surf + 1000 * hat_d_sun + lambda_5 * hat_p_surf; // STEP 6: Local Illumination Direction Vector3D hat_d_local = (p_local - c_pos).unit(); /// STEP 7: Projection of the Local Illumination Point to the Image Plane Vector3D k = c_pos + sc.getPOVDirection(); Vector3D c_up = sc.getPOVUp(); Vector3D c_right = sc.getPOVRight(); double w = Convert.ToDouble(this._width); double h = Convert.ToDouble(this._height); double x2 = ( -2 * w * c_pos.y() * c_up.z() * hat_d_local.x() - c_right.y() * c_up.z() * hat_d_local.x() - w * c_right.y() * c_up.z() * hat_d_local.x() + 2 * w * c_pos.x() * c_up.z() * hat_d_local.y() + c_right.x() * c_up.z() * hat_d_local.y() + w * c_right.x() * c_up.z() * hat_d_local.y() + 2 * w * c_pos.z() * (c_up.y() * hat_d_local.x() - c_up.x() * hat_d_local.y()) + (1 + w) * c_right.z() * (c_up.y() * hat_d_local.x() - c_up.x() * hat_d_local.y()) + 2 * w * c_pos.y() * c_up.x() * hat_d_local.z() + c_right.y() * c_up.x() * hat_d_local.z() + w * c_right.y() * c_up.x() * hat_d_local.z() - 2 * w * c_pos.x() * c_up.y() * hat_d_local.z() - c_right.x() * c_up.y() * hat_d_local.z() - w * c_right.x() * c_up.y() * hat_d_local.z() - 2 * w * c_up.z() * hat_d_local.y() * k.x() + 2 * w * c_up.y() * hat_d_local.z() * k.x() + 2 * w * c_up.z() * hat_d_local.x() * k.y() - 2 * w * c_up.x() * hat_d_local.z() * k.y() - 2 * w * c_up.y() * hat_d_local.x() * k.z() + 2 * w * c_up.x() * hat_d_local.y() * k.z() )/( 2 * (c_right.z() * (c_up.y() * hat_d_local.x() - c_up.x() * hat_d_local.y()) + c_right.y() * (-c_up.z() * hat_d_local.x() + c_up.x() * hat_d_local.z()) + c_right.x() * (c_up.z() * hat_d_local.y() - c_up.y() * hat_d_local.z())) ); double y2 = ( -c_right.z() * c_up.y() * hat_d_local.x() - h * c_right.z() * c_up.y() * hat_d_local.x() + c_right.y() * c_up.z() * hat_d_local.x() + h * c_right.y() * c_up.z() * hat_d_local.x() - 2 * h * c_pos.x() * c_right.z() * hat_d_local.y() + c_right.z() * c_up.x() * hat_d_local.y() + h * c_right.z() * c_up.x() * hat_d_local.y() - c_right.x() * c_up.z() * hat_d_local.y() - h * c_right.x() * c_up.z() * hat_d_local.y() + c_pos.z() * (-2 * h * c_right.y() * hat_d_local.x() + 2 * h * c_right.x() * hat_d_local.y()) + 2 * h * c_pos.x() * c_right.y() * hat_d_local.z() - c_right.y() * c_up.x() * hat_d_local.z() - h * c_right.y() * c_up.x() * hat_d_local.z() + c_right.x() * c_up.y() * hat_d_local.z() + h * c_right.x() * c_up.y() * hat_d_local.z() + 2 * h * c_pos.y() * (c_right.z() * hat_d_local.x() - c_right.x() * hat_d_local.z()) + 2 * h * c_right.z() * hat_d_local.y() * k.x() - 2 * h * c_right.y() * hat_d_local.z() * k.x() - 2 * h * c_right.z() * hat_d_local.x() * k.y() + 2 * h * c_right.x() * hat_d_local.z() * k.y() + 2 * h * c_right.y() * hat_d_local.x() * k.z() - 2 * h * c_right.x() * hat_d_local.y() * k.z() )/( 2 * (c_right.z() * (-c_up.y() * hat_d_local.x() + c_up.x() * hat_d_local.y()) + c_right.y() * (c_up.z() * hat_d_local.x() - c_up.x() * hat_d_local.z()) + c_right.x() * (-c_up.z() * hat_d_local.y() + c_up.y() * hat_d_local.z())) ); // STEP 8: The Local Solar Illumination Angle Vector2D v1 = new Vector2D(0, 1000); Vector2D v2 = new Vector2D(x2-x1, y2-y1); if (v2.x() > 0) { PixelOut.IlluminationAngle = tools.rad2deg(Math.Acos((v1 * v2) / (v1.norm() * v2.norm()))); } else { PixelOut.IlluminationAngle = tools.rad2deg(2 * Math.PI - Math.Acos((v1 * v2) / (v1.norm() * v2.norm()))); } PixelOut.exists = true; return PixelOut; } else { // next grid sample point return PixelOut; } }