public Vector3d calculateVelocity(double timeEpoch, CelestialBody relativeTo, bool isFromDelta) { if (orbitalElements == null) { return(new Vector3d(0, 0, 0)); } var eclipticVelocity = new Vector3d(); if (isFromDelta) { Vector3d pos1 = calculatePosition(timeEpoch); Vector3d pos2 = calculatePosition(timeEpoch + 60); eclipticVelocity = (pos2 - pos1) * (1.0 / 60.0); } else { //vis viva to calculate speed (not velocity, i.e not a vector) OrbitalElementsPieces el = calculateElements(timeEpoch); double speed = Math.Sqrt(SO.G * SO.U.getBody(relativeTo).mass *((2.0 / (el.r.Value)) - (1.0 / (el.a.Value)))); //now calculate velocity orientation, that is, a vector tangent to the orbital ellipse double?k = el.r / el.a; double?o = ((2 - (2 * el.e * el.e)) / (k * (2 - k))) - 1; //floating point imprecision o = o > 1 ? 1 : o; double alpha = Math.PI - Math.Acos(o.Value); alpha = el.v < 0 ? (2 * Math.PI) - alpha : alpha; double velocityAngle = el.v.Value + (alpha / 2); //velocity vector in the plane of the orbit Vector3d orbitalVelocity = new Vector3d(Math.Cos(velocityAngle), Math.Sin(velocityAngle), 0).normalized *speed; OrbitalElementsPieces velocityEls = el.Copy(); velocityEls.pos = orbitalVelocity; velocityEls.v = 0; velocityEls.r = 0; eclipticVelocity = getPositionFromElements(velocityEls); } //var diff = eclipticVelocityFromDelta.sub(eclipticVelocity);console.log(diff.length()); return(eclipticVelocity); }
public OrbitalElementsPieces calculateElements(double timeEpoch, OrbitalElementsPieces forcedOrbitalElements = null) { if (forcedOrbitalElements == null && this.orbitalElements == null) { return(null); } /* Debug.Log(this.name); * * Debug.Log(this.orbitalElements); * Debug.Log(this.orbitalElements.cy);*/ OrbitalElementsPieces orbitalElements = forcedOrbitalElements ?? this.orbitalElements; /* * * Epoch : J2000 * * a Semi-major axis * e Eccentricity * i Inclination * o Longitude of Ascending Node (Ω) * w Argument of periapsis (ω) * E Eccentric Anomaly * T Time at perihelion * M Mean anomaly * l Mean Longitude * lp longitude of periapsis * r distance du centre * v true anomaly * * P Sidereal period (mean value) * Pw Argument of periapsis precession period (mean value) * Pn Longitude of the ascending node precession period (mean value) * */ if (epochCorrection.HasValue) { timeEpoch -= epochCorrection.Value; } double tDays = timeEpoch / SO.DAY; double T = tDays / SO.CENTURY; //console.log(T); var computed = new OrbitalElementsPieces(); computed.t = timeEpoch; if (calculator != null && forcedOrbitalElements == null) { OrbitalElementsPieces realorbit = calculator(T); computed = realorbit.Copy(); } else { if (orbitalElements.baseElements != null) { double variation = 0.0; CalculateVariation(orbitalElements, orbitalElements.GetType().GetField("a"), computed, T); CalculateVariation(orbitalElements, orbitalElements.GetType().GetField("e"), computed, T); CalculateVariation(orbitalElements, orbitalElements.GetType().GetField("i"), computed, T); CalculateVariation(orbitalElements, orbitalElements.GetType().GetField("l"), computed, T); CalculateVariation(orbitalElements, orbitalElements.GetType().GetField("lp"), computed, T); CalculateVariation(orbitalElements, orbitalElements.GetType().GetField("o"), computed, T); CalculateVariation(orbitalElements, orbitalElements.GetType().GetField("E"), computed, T); CalculateVariation(orbitalElements, orbitalElements.GetType().GetField("M"), computed, T); CalculateVariation(orbitalElements, orbitalElements.GetType().GetField("r"), computed, T); //CalculateVariation(orbitalElements, orbitalElements.GetType().GetField("t"), computed, T); CalculateVariation(orbitalElements, orbitalElements.GetType().GetField("v"), computed, T); CalculateVariation(orbitalElements, orbitalElements.GetType().GetField("w"), computed, T); /* * variation = orbitalElements.cy ? orbitalElements.cy[el] : (orbitalElements.day[el] * ns.CENTURY); * variation = variation || 0; * computed[el] = orbitalElements.base[el] + (variation * T); */ // Bomb } else { computed = orbitalElements.Copy(); } if (!computed.w.HasValue) { computed.w = computed.lp - computed.o; } if (!computed.M.HasValue) { computed.M = computed.l - computed.lp; } computed.a = computed.a * SO.KM; //was in km, set it in m } computed.i = SO.DEG_TO_RAD * computed.i; computed.o = SO.DEG_TO_RAD * computed.o; computed.w = SO.DEG_TO_RAD * computed.w; computed.M = SO.DEG_TO_RAD * computed.M; computed.E = solveEccentricAnomaly(computed.e.Value, computed.M.Value); computed.E = computed.E % SO.CIRCLE; computed.i = computed.i % SO.CIRCLE; computed.o = computed.o % SO.CIRCLE; computed.w = computed.w % SO.CIRCLE; computed.M = computed.M % SO.CIRCLE; //in the plane of the orbit computed.pos = new Vector3d((computed.a * (Math.Cos(computed.E.Value) - computed.e.Value)).Value, (computed.a.Value * (Math.Sqrt(1 - (computed.e.Value * computed.e.Value))) * Math.Sin(computed.E.Value))); computed.r = computed.pos.magnitude; computed.v = Math.Atan2(computed.pos.y, computed.pos.x); if (orbitalElements.relativeTo != null) { var relativeTo = SO.U.getBody(orbitalElements.relativeTo); if (relativeTo.tilt.HasValue) { computed.tilt = -relativeTo.tilt.Value * SO.DEG_TO_RAD; } } return(computed); }