本文整理汇总了C#中Orbit.SwappedOrbitNormal方法的典型用法代码示例。如果您正苦于以下问题:C# Orbit.SwappedOrbitNormal方法的具体用法?C# Orbit.SwappedOrbitNormal怎么用?C# Orbit.SwappedOrbitNormal使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类Orbit
的用法示例。
在下文中一共展示了Orbit.SwappedOrbitNormal方法的11个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C#代码示例。
示例1: TimeToPhaseAngle
//Computes the time until the phase angle between the launchpad and the target equals the given angle.
//The convention used is that phase angle is the angle measured starting at the target and going east until
//you get to the launchpad.
//The time returned will not be exactly accurate unless the target is in an exactly circular orbit. However,
//the time returned will go to exactly zero when the desired phase angle is reached.
public static double TimeToPhaseAngle(double phaseAngle, CelestialBody launchBody, double launchLongitude, Orbit target)
{
double launchpadAngularRate = 360 / launchBody.rotationPeriod;
double targetAngularRate = 360.0 / target.period;
if (Vector3d.Dot(target.SwappedOrbitNormal(), launchBody.angularVelocity) < 0) targetAngularRate *= -1; //retrograde target
Vector3d currentLaunchpadDirection = launchBody.GetSurfaceNVector(0, launchLongitude);
Vector3d currentTargetDirection = target.SwappedRelativePositionAtUT(Planetarium.GetUniversalTime());
currentTargetDirection = Vector3d.Exclude(launchBody.angularVelocity, currentTargetDirection);
double currentPhaseAngle = Math.Abs(Vector3d.Angle(currentLaunchpadDirection, currentTargetDirection));
if (Vector3d.Dot(Vector3d.Cross(currentTargetDirection, currentLaunchpadDirection), launchBody.angularVelocity) < 0)
{
currentPhaseAngle = 360 - currentPhaseAngle;
}
double phaseAngleRate = launchpadAngularRate - targetAngularRate;
double phaseAngleDifference = MuUtils.ClampDegrees360(phaseAngle - currentPhaseAngle);
if (phaseAngleRate < 0)
{
phaseAngleRate *= -1;
phaseAngleDifference = 360 - phaseAngleDifference;
}
return phaseAngleDifference / phaseAngleRate;
}
示例2: DeltaVAndTimeForCheapestCourseCorrection
public static Vector3d DeltaVAndTimeForCheapestCourseCorrection(Orbit o, double UT, Orbit target, CelestialBody targetBody, double finalPeR, out double burnUT)
{
Vector3d collisionDV = DeltaVAndTimeForCheapestCourseCorrection(o, UT, target, out burnUT);
Orbit collisionOrbit = o.PerturbedOrbit(burnUT, collisionDV);
double collisionUT = collisionOrbit.NextClosestApproachTime(target, burnUT);
Vector3d collisionPosition = target.SwappedAbsolutePositionAtUT(collisionUT);
Vector3d collisionRelVel = collisionOrbit.SwappedOrbitalVelocityAtUT(collisionUT) - target.SwappedOrbitalVelocityAtUT(collisionUT);
double soiEnterUT = collisionUT - targetBody.sphereOfInfluence / collisionRelVel.magnitude;
Vector3d soiEnterRelVel = collisionOrbit.SwappedOrbitalVelocityAtUT(soiEnterUT) - target.SwappedOrbitalVelocityAtUT(soiEnterUT);
double E = 0.5 * soiEnterRelVel.sqrMagnitude - targetBody.gravParameter / targetBody.sphereOfInfluence; //total orbital energy on SoI enter
double finalPeSpeed = Math.Sqrt(2 * (E + targetBody.gravParameter / finalPeR)); //conservation of energy gives the orbital speed at finalPeR.
double desiredImpactParameter = finalPeR * finalPeSpeed / soiEnterRelVel.magnitude; //conservation of angular momentum gives the required impact parameter
Vector3d displacementDir = Vector3d.Cross(collisionRelVel, o.SwappedOrbitNormal()).normalized;
Vector3d interceptTarget = collisionPosition + desiredImpactParameter * displacementDir;
Vector3d velAfterBurn;
Vector3d arrivalVel;
LambertSolver.Solve(o.SwappedRelativePositionAtUT(burnUT), interceptTarget - o.referenceBody.position, collisionUT - burnUT, o.referenceBody, true, out velAfterBurn, out arrivalVel);
Vector3d deltaV = velAfterBurn - o.SwappedOrbitalVelocityAtUT(burnUT);
return deltaV;
}
示例3: TimeToPlane
//From MechJeb2
//Computes the time required for the given launch location to rotate under the target orbital plane.
//If the latitude is too high for the launch location to ever actually rotate under the target plane,
//returns the time of closest approach to the target plane.
//I have a wonderful proof of this formula which this comment is too short to contain.
internal static double TimeToPlane(CelestialBody launchBody, double launchLatitude, double launchLongitude, Orbit target)
{
double inc = Math.Abs(Vector3d.Angle(target.SwappedOrbitNormal(), launchBody.angularVelocity));
Vector3d b = Vector3d.Exclude(launchBody.angularVelocity, target.SwappedOrbitNormal()).normalized; // I don't understand the sign here, but this seems to work
b *= launchBody.Radius * Math.Sin(Math.PI / 180 * launchLatitude) / Math.Tan(Math.PI / 180 * inc);
Vector3d c = Vector3d.Cross(target.SwappedOrbitNormal(), launchBody.angularVelocity).normalized;
double cMagnitudeSquared = Math.Pow(launchBody.Radius * Math.Cos(Math.PI / 180 * launchLatitude), 2) - b.sqrMagnitude;
if (cMagnitudeSquared < 0) cMagnitudeSquared = 0;
c *= Math.Sqrt(cMagnitudeSquared);
Vector3d a1 = b + c;
Vector3d a2 = b - c;
Vector3d longitudeVector = launchBody.GetSurfaceNVector(0, launchLongitude);
double angle1 = Math.Abs(Vector3d.Angle(longitudeVector, a1));
if (Vector3d.Dot(Vector3d.Cross(longitudeVector, a1), launchBody.angularVelocity) < 0) angle1 = 360 - angle1;
double angle2 = Math.Abs(Vector3d.Angle(longitudeVector, a2));
if (Vector3d.Dot(Vector3d.Cross(longitudeVector, a2), launchBody.angularVelocity) < 0) angle2 = 360 - angle2;
double angle = Math.Min(angle1, angle2);
return (angle / 360) * launchBody.rotationPeriod;
}
示例4: MakeNodeImpl
public override ManeuverParameters MakeNodeImpl(Orbit o, double UT, MechJebModuleTargetController target)
{
// Check preconditions
if (!target.NormalTargetExists)
throw new OperationException("must select a target for the interplanetary transfer.");
if (o.referenceBody.referenceBody == null)
throw new OperationException("doesn't make sense to plot an interplanetary transfer from an orbit around " + o.referenceBody.theName + ".");
if (o.referenceBody.referenceBody != target.TargetOrbit.referenceBody)
{
if (o.referenceBody == target.TargetOrbit.referenceBody)
throw new OperationException("use regular Hohmann transfer function to intercept another body orbiting " + o.referenceBody.theName + ".");
throw new OperationException("an interplanetary transfer from within " + o.referenceBody.theName + "'s sphere of influence must target a body that orbits " + o.referenceBody.theName + "'s parent, " + o.referenceBody.referenceBody.theName + ".");
}
// Simple warnings
if (o.referenceBody.orbit.RelativeInclination(target.TargetOrbit) > 30)
{
errorMessage = "Warning: target's orbital plane is at a " + o.RelativeInclination(target.TargetOrbit).ToString("F0") + "º angle to " + o.referenceBody.theName + "'s orbital plane (recommend at most 30º). Planned interplanetary transfer may not intercept target properly.";
}
else
{
double relativeInclination = Vector3d.Angle(o.SwappedOrbitNormal(), o.referenceBody.orbit.SwappedOrbitNormal());
if (relativeInclination > 10)
{
errorMessage = "Warning: Recommend starting interplanetary transfers from " + o.referenceBody.theName + " from an orbit in the same plane as " + o.referenceBody.theName + "'s orbit around " + o.referenceBody.referenceBody.theName + ". Starting orbit around " + o.referenceBody.theName + " is inclined " + relativeInclination.ToString("F1") + "º with respect to " + o.referenceBody.theName + "'s orbit around " + o.referenceBody.referenceBody.theName + " (recommend < 10º). Planned transfer may not intercept target properly.";
}
else if (o.eccentricity > 0.2)
{
errorMessage = "Warning: Recommend starting interplanetary transfers from a near-circular orbit (eccentricity < 0.2). Planned transfer is starting from an orbit with eccentricity " + o.eccentricity.ToString("F2") + " and so may not intercept target properly.";
}
}
var dV = OrbitalManeuverCalculator.DeltaVAndTimeForInterplanetaryTransferEjection(o, UT, target.TargetOrbit, waitForPhaseAngle, out UT);
return new ManeuverParameters(dV, UT);
}
示例5: DeltaVAndTimeToMatchPlanesDescending
//Computes the delta-V and time of a burn to match planes with the target orbit. The output burnUT
//will be equal to the time of the first descending node with respect to the target after the given UT.
//Throws an ArgumentException if o is hyperbolic and doesn't have a descending node relative to the target.
public static Vector3d DeltaVAndTimeToMatchPlanesDescending(Orbit o, Orbit target, double UT, out double burnUT)
{
burnUT = o.TimeOfDescendingNode(target, UT);
Vector3d desiredHorizontal = Vector3d.Cross(target.SwappedOrbitNormal(), o.Up(burnUT));
Vector3d actualHorizontalVelocity = Vector3d.Exclude(o.Up(burnUT), o.SwappedOrbitalVelocityAtUT(burnUT));
Vector3d desiredHorizontalVelocity = actualHorizontalVelocity.magnitude * desiredHorizontal;
return desiredHorizontalVelocity - actualHorizontalVelocity;
}
示例6: DeltaVAndTimeForInterplanetaryTransferEjection
//Computes the time and delta-V of an ejection burn to a Hohmann transfer from one planet to another.
//It's assumed that the initial orbit around the first planet is circular, and that this orbit
//is in the same plane as the orbit of the first planet around the sun. It's also assumed that
//the target planet has a fairly low relative inclination with respect to the first planet. If the
//inclination change is nonzero you should also do a mid-course correction burn, as computed by
//DeltaVForCourseCorrection.
public static Vector3d DeltaVAndTimeForInterplanetaryTransferEjection(Orbit o, double UT, Orbit target, bool syncPhaseAngle, out double burnUT)
{
Orbit planetOrbit = o.referenceBody.orbit;
//Compute the time and dV for a Hohmann transfer where we pretend that we are the planet we are orbiting.
//This gives us the "ideal" deltaV and UT of the ejection burn, if we didn't have to worry about waiting for the right
//ejection angle and if we didn't have to worry about the planet's gravity dragging us back and increasing the required dV.
double idealBurnUT;
Vector3d idealDeltaV;
if (syncPhaseAngle)
{
//time the ejection burn to intercept the target
idealDeltaV = DeltaVAndTimeForHohmannTransfer(planetOrbit, target, UT, out idealBurnUT);
}
else
{
//don't time the ejection burn to intercept the target; we just care about the final peri/apoapsis
idealBurnUT = UT;
if (target.semiMajorAxis < planetOrbit.semiMajorAxis) idealDeltaV = DeltaVToChangePeriapsis(planetOrbit, idealBurnUT, target.semiMajorAxis);
else idealDeltaV = DeltaVToChangeApoapsis(planetOrbit, idealBurnUT, target.semiMajorAxis);
}
//Compute the actual transfer orbit this ideal burn would lead to.
Orbit transferOrbit = planetOrbit.PerturbedOrbit(idealBurnUT, idealDeltaV);
//Now figure out how to approximately eject from our current orbit into the Hohmann orbit we just computed.
//Assume we want to exit the SOI with the same velocity as the ideal transfer orbit at idealUT -- i.e., immediately
//after the "ideal" burn we used to compute the transfer orbit. This isn't quite right.
//We intend to eject from our planet at idealUT and only several hours later will we exit the SOI. Meanwhile
//the transfer orbit will have acquired a slightly different velocity, which we should correct for. Maybe
//just add in (1/2)(sun gravity)*(time to exit soi)^2 ? But how to compute time to exit soi? Or maybe once we
//have the ejection orbit we should just move the ejection burn back by the time to exit the soi?
Vector3d soiExitVelocity = idealDeltaV;
//project the desired exit direction into the current orbit plane to get the feasible exit direction
Vector3d inPlaneSoiExitDirection = Vector3d.Exclude(o.SwappedOrbitNormal(), soiExitVelocity).normalized;
//compute the angle by which the trajectory turns between periapsis (where we do the ejection burn)
//and SOI exit (approximated as radius = infinity)
double soiExitEnergy = 0.5 * soiExitVelocity.sqrMagnitude - o.referenceBody.gravParameter / o.referenceBody.sphereOfInfluence;
double ejectionRadius = o.semiMajorAxis; //a guess, good for nearly circular orbits
double ejectionKineticEnergy = soiExitEnergy + o.referenceBody.gravParameter / ejectionRadius;
double ejectionSpeed = Math.Sqrt(2 * ejectionKineticEnergy);
//construct a sample ejection orbit
Vector3d ejectionOrbitInitialVelocity = ejectionSpeed * (Vector3d)o.referenceBody.transform.right;
Vector3d ejectionOrbitInitialPosition = o.referenceBody.position + ejectionRadius * (Vector3d)o.referenceBody.transform.up;
Orbit sampleEjectionOrbit = MuUtils.OrbitFromStateVectors(ejectionOrbitInitialPosition, ejectionOrbitInitialVelocity, o.referenceBody, 0);
double ejectionOrbitDuration = sampleEjectionOrbit.NextTimeOfRadius(0, o.referenceBody.sphereOfInfluence);
Vector3d ejectionOrbitFinalVelocity = sampleEjectionOrbit.SwappedOrbitalVelocityAtUT(ejectionOrbitDuration);
double turningAngle = Math.Abs(Vector3d.Angle(ejectionOrbitInitialVelocity, ejectionOrbitFinalVelocity));
//rotate the exit direction by 90 + the turning angle to get a vector pointing to the spot in our orbit
//where we should do the ejection burn. Then convert this to a true anomaly and compute the time closest
//to planetUT at which we will pass through that true anomaly.
Vector3d ejectionPointDirection = Quaternion.AngleAxis(-(float)(90 + turningAngle), o.SwappedOrbitNormal()) * inPlaneSoiExitDirection;
double ejectionTrueAnomaly = o.TrueAnomalyFromVector(ejectionPointDirection);
burnUT = o.TimeOfTrueAnomaly(ejectionTrueAnomaly, idealBurnUT - o.period);
if ((idealBurnUT - burnUT > o.period / 2) || (burnUT < UT))
{
burnUT += o.period;
}
//rotate the exit direction by the turning angle to get a vector pointing to the spot in our orbit
//where we should do the ejection burn
Vector3d ejectionBurnDirection = Quaternion.AngleAxis(-(float)(turningAngle), o.SwappedOrbitNormal()) * inPlaneSoiExitDirection;
Vector3d ejectionVelocity = ejectionSpeed * ejectionBurnDirection;
Vector3d preEjectionVelocity = o.SwappedOrbitalVelocityAtUT(burnUT);
return ejectionVelocity - preEjectionVelocity;
}
示例7: RelativeInclination
//Computes the angle between two orbital planes. This will be a number between 0 and 180
//Note that in the convention used two objects orbiting in the same plane but in
//opposite directions have a relative inclination of 180 degrees.
public static double RelativeInclination(this Orbit a, Orbit b)
{
return Math.Abs(Vector3d.Angle(a.SwappedOrbitNormal(), b.SwappedOrbitNormal()));
}
示例8: SynodicPeriod
//Computes the period of the phase angle between orbiting objects a and b.
//This only really makes sense for approximately circular orbits in similar planes.
//For noncircular orbits the time variation of the phase angle is only "quasiperiodic"
//and for high eccentricities and/or large relative inclinations, the relative motion is
//not really periodic at all.
public static double SynodicPeriod(this Orbit a, Orbit b)
{
int sign = (Vector3d.Dot(a.SwappedOrbitNormal(), b.SwappedOrbitNormal()) > 0 ? 1 : -1); //detect relative retrograde motion
return Math.Abs(1.0 / (1.0 / a.period - sign * 1.0 / b.period)); //period after which the phase angle repeats
}
示例9: AscendingNodeTrueAnomaly
//Gives the true anomaly (in a's orbit) at which a crosses its ascending node
//with b's orbit.
//The returned value is always between 0 and 360.
public static double AscendingNodeTrueAnomaly(this Orbit a, Orbit b)
{
Vector3d vectorToAN = Vector3d.Cross(a.SwappedOrbitNormal(), b.SwappedOrbitNormal());
return a.TrueAnomalyFromVector(vectorToAN);
}
示例10: DeltaVAndTimeForInterplanetaryLambertTransferEjection
//Computes the time and delta-V of an ejection burn to a Hohmann transfer from one planet to another.
//It's assumed that the initial orbit around the first planet is circular, and that this orbit
//is in the same plane as the orbit of the first planet around the sun. It's also assumed that
//the target planet has a fairly low relative inclination with respect to the first planet. If the
//inclination change is nonzero you should also do a mid-course correction burn, as computed by
//DeltaVForCourseCorrection.
public static Vector3d DeltaVAndTimeForInterplanetaryLambertTransferEjection(Orbit o, double UT, Orbit target, out double burnUT)
{
Orbit planetOrbit = o.referenceBody.orbit;
//Compute the time and dV for a Hohmann transfer where we pretend that we are the planet we are orbiting.
//This gives us the "ideal" deltaV and UT of the ejection burn, if we didn't have to worry about waiting for the right
//ejection angle and if we didn't have to worry about the planet's gravity dragging us back and increasing the required dV.
double idealBurnUT;
Vector3d idealDeltaV;
//time the ejection burn to intercept the target
//idealDeltaV = DeltaVAndTimeForHohmannTransfer(planetOrbit, target, UT, out idealBurnUT);
double vesselOrbitVelocity = OrbitalManeuverCalculator.CircularOrbitSpeed(o.referenceBody, o.semiMajorAxis);
idealDeltaV = DeltaVAndTimeForHohmannLambertTransfer(planetOrbit, target, UT, out idealBurnUT, vesselOrbitVelocity);
Debug.Log("idealBurnUT = " + idealBurnUT + ", idealDeltaV = " + idealDeltaV);
//Compute the actual transfer orbit this ideal burn would lead to.
Orbit transferOrbit = planetOrbit.PerturbedOrbit(idealBurnUT, idealDeltaV);
//Now figure out how to approximately eject from our current orbit into the Hohmann orbit we just computed.
//Assume we want to exit the SOI with the same velocity as the ideal transfer orbit at idealUT -- i.e., immediately
//after the "ideal" burn we used to compute the transfer orbit. This isn't quite right.
//We intend to eject from our planet at idealUT and only several hours later will we exit the SOI. Meanwhile
//the transfer orbit will have acquired a slightly different velocity, which we should correct for. Maybe
//just add in (1/2)(sun gravity)*(time to exit soi)^2 ? But how to compute time to exit soi? Or maybe once we
//have the ejection orbit we should just move the ejection burn back by the time to exit the soi?
Vector3d soiExitVelocity = idealDeltaV;
Debug.Log("soiExitVelocity = " + (Vector3)soiExitVelocity);
//compute the angle by which the trajectory turns between periapsis (where we do the ejection burn)
//and SOI exit (approximated as radius = infinity)
double soiExitEnergy = 0.5 * soiExitVelocity.sqrMagnitude - o.referenceBody.gravParameter / o.referenceBody.sphereOfInfluence;
double ejectionRadius = o.semiMajorAxis; //a guess, good for nearly circular orbits
Debug.Log("soiExitEnergy = " + soiExitEnergy);
Debug.Log("ejectionRadius = " + ejectionRadius);
double ejectionKineticEnergy = soiExitEnergy + o.referenceBody.gravParameter / ejectionRadius;
double ejectionSpeed = Math.Sqrt(2 * ejectionKineticEnergy);
Debug.Log("ejectionSpeed = " + ejectionSpeed);
//construct a sample ejection orbit
Vector3d ejectionOrbitInitialVelocity = ejectionSpeed * (Vector3d)o.referenceBody.transform.right;
Vector3d ejectionOrbitInitialPosition = o.referenceBody.position + ejectionRadius * (Vector3d)o.referenceBody.transform.up;
Orbit sampleEjectionOrbit = MuUtils.OrbitFromStateVectors(ejectionOrbitInitialPosition, ejectionOrbitInitialVelocity, o.referenceBody, 0);
double ejectionOrbitDuration = sampleEjectionOrbit.NextTimeOfRadius(0, o.referenceBody.sphereOfInfluence);
Vector3d ejectionOrbitFinalVelocity = sampleEjectionOrbit.SwappedOrbitalVelocityAtUT(ejectionOrbitDuration);
double turningAngle = Vector3d.Angle(ejectionOrbitInitialVelocity, ejectionOrbitFinalVelocity);
Debug.Log("turningAngle = " + turningAngle);
//sine of the angle between the vessel orbit and the desired SOI exit velocity
double outOfPlaneAngle = (Math.PI / 180) * (90 - Vector3d.Angle(soiExitVelocity, o.SwappedOrbitNormal()));
Debug.Log("outOfPlaneAngle (rad) = " + outOfPlaneAngle);
double coneAngle = Math.PI / 2 - (Math.PI / 180) * turningAngle;
Debug.Log("coneAngle (rad) = " + coneAngle);
Vector3d exitNormal = Vector3d.Cross(-soiExitVelocity, o.SwappedOrbitNormal()).normalized;
Vector3d normal2 = Vector3d.Cross(exitNormal, -soiExitVelocity).normalized;
//unit vector pointing to the spot on our orbit where we will burn.
//fails if outOfPlaneAngle > coneAngle.
Vector3d ejectionPointDirection = Math.Cos(coneAngle) * (-soiExitVelocity.normalized)
+ Math.Cos(coneAngle) * Math.Tan(outOfPlaneAngle) * normal2
- Math.Sqrt(Math.Pow(Math.Sin(coneAngle), 2) - Math.Pow(Math.Cos(coneAngle) * Math.Tan(outOfPlaneAngle), 2)) * exitNormal;
Debug.Log("soiExitVelocity = " + (Vector3)soiExitVelocity);
Debug.Log("vessel orbit normal = " + (Vector3)(1000 * o.SwappedOrbitNormal()));
Debug.Log("exitNormal = " + (Vector3)(1000 * exitNormal));
Debug.Log("normal2 = " + (Vector3)(1000 * normal2));
Debug.Log("ejectionPointDirection = " + ejectionPointDirection);
double ejectionTrueAnomaly = o.TrueAnomalyFromVector(ejectionPointDirection);
burnUT = o.TimeOfTrueAnomaly(ejectionTrueAnomaly, idealBurnUT - o.period);
if ((idealBurnUT - burnUT > o.period / 2) || (burnUT < UT))
{
burnUT += o.period;
}
Vector3d ejectionOrbitNormal = Vector3d.Cross(ejectionPointDirection, soiExitVelocity).normalized;
Debug.Log("ejectionOrbitNormal = " + ejectionOrbitNormal);
Vector3d ejectionBurnDirection = Quaternion.AngleAxis(-(float)(turningAngle), ejectionOrbitNormal) * soiExitVelocity.normalized;
Debug.Log("ejectionBurnDirection = " + ejectionBurnDirection);
Vector3d ejectionVelocity = ejectionSpeed * ejectionBurnDirection;
Vector3d preEjectionVelocity = o.SwappedOrbitalVelocityAtUT(burnUT);
return ejectionVelocity - preEjectionVelocity;
}
示例11: CheckPreconditions
//.........这里部分代码省略.........
errorMessage = "Warning: Recommend starting Hohmann transfers from a near-circular orbit (eccentricity < 0.2). Planned transfer is starting from an orbit with eccentricity " + o.eccentricity.ToString("F2") + " and so may not intercept target properly.";
}
break;
case Operation.COURSE_CORRECTION:
if (!core.target.NormalTargetExists)
{
error = true;
errorMessage = "must select a target for the course correction.";
}
else if (o.referenceBody != core.target.Orbit.referenceBody)
{
error = true;
errorMessage = "target for course correction must be in the same sphere of influence";
}
else if (o.NextClosestApproachTime(core.target.Orbit, UT) < UT + 1 ||
o.NextClosestApproachDistance(core.target.Orbit, UT) > core.target.Orbit.semiMajorAxis * 0.2)
{
errorMessage = "Warning: orbit before course correction doesn't seem to approach target very closely. Planned course correction may be extreme. Recommend plotting an approximate intercept orbit and then plotting a course correction.";
}
break;
case Operation.INTERPLANETARY_TRANSFER:
if (!core.target.NormalTargetExists)
{
error = true;
errorMessage = "must select a target for the interplanetary transfer.";
}
else if (o.referenceBody.referenceBody == null)
{
error = true;
errorMessage = "doesn't make sense to plot an interplanetary transfer from an orbit around " + o.referenceBody.theName + ".";
}
else if (o.referenceBody.referenceBody != core.target.Orbit.referenceBody)
{
error = true;
if (o.referenceBody == core.target.Orbit.referenceBody) errorMessage = "use regular Hohmann transfer function to intercept another body orbiting " + o.referenceBody.theName + ".";
else errorMessage = "an interplanetary transfer from within " + o.referenceBody.theName + "'s sphere of influence must target a body that orbits " + o.referenceBody.theName + "'s parent, " + o.referenceBody.referenceBody.theName + ".";
}
else if (o.referenceBody.orbit.RelativeInclination(core.target.Orbit) > 30)
{
errorMessage = "Warning: target's orbital plane is at a " + o.RelativeInclination(core.target.Orbit).ToString("F0") + "º angle to " + o.referenceBody.theName + "'s orbital plane (recommend at most 30º). Planned interplanetary transfer may not intercept target properly.";
}
else
{
double relativeInclination = Vector3d.Angle(o.SwappedOrbitNormal(), o.referenceBody.orbit.SwappedOrbitNormal());
if (relativeInclination > 10)
{
errorMessage = "Warning: Recommend starting interplanetary transfers from " + o.referenceBody.theName + " from an orbit in the same plane as " + o.referenceBody.theName + "'s orbit around " + o.referenceBody.referenceBody.theName + ". Starting orbit around " + o.referenceBody.theName + " is inclined " + relativeInclination.ToString("F1") + "º with respect to " + o.referenceBody.theName + "'s orbit around " + o.referenceBody.referenceBody.theName + " (recommend < 10º). Planned transfer may not intercept target properly.";
}
else if (o.eccentricity > 0.2)
{
errorMessage = "Warning: Recommend starting interplanetary transfers from a near-circular orbit (eccentricity < 0.2). Planned transfer is starting from an orbit with eccentricity " + o.eccentricity.ToString("F2") + " and so may not intercept target properly.";
}
}
break;
case Operation.MOON_RETURN:
if (o.referenceBody.referenceBody == null)
{
error = true;
errorMessage = o.referenceBody.theName + " is not orbiting another body you could return to.";
}
else if (o.eccentricity > 0.2)
{
errorMessage = "Warning: Recommend starting moon returns from a near-circular orbit (eccentricity < 0.2). Planned return is starting from an orbit with eccentricity " + o.eccentricity.ToString("F2") + " and so may not be accurate.";
}
break;
case Operation.LAMBERT:
if (!core.target.NormalTargetExists)
{
error = true;
errorMessage = "must select a target to intercept.";
}
else if (o.referenceBody != core.target.Orbit.referenceBody)
{
error = true;
errorMessage = "target must be in the same sphere of influence.";
}
break;
case Operation.KILL_RELVEL:
if (!core.target.NormalTargetExists)
{
error = true;
errorMessage = "must select a target to match velocities with.";
}
else if (o.referenceBody != core.target.Orbit.referenceBody)
{
error = true;
errorMessage = "target must be in the same sphere of influence.";
}
break;
}
if (error) errorMessage = "Couldn't plot maneuver: " + errorMessage;
return !error;
}