private static string Description(FrameType type, CelestialBody selected) { switch (type) { case FrameType.BODY_CENTRED_NON_ROTATING: return(L10N.CelestialString( "#Principia_ReferenceFrameSelector_Description_BodyCentredNonRotating", new[] { selected })); case FrameType.BARYCENTRIC_ROTATING: return("DEPRECATED"); case FrameType.BODY_CENTRED_PARENT_DIRECTION: if (selected.is_root()) { throw Log.Fatal( "Describing parent-direction rotating frame of root body"); } else { return(L10N.CelestialString( "#Principia_ReferenceFrameSelector_Description_BodyCentredParentDirection", new[] { selected, selected.referenceBody })); } case FrameType.BODY_SURFACE: return(L10N.CelestialString( "#Principia_ReferenceFrameSelector_Description_BodySurface", new[] { selected })); default: throw Log.Fatal("Unexpected type " + type.ToString()); } }
private void RenderOrbitalElements(OrbitalElements?elements, CelestialBody primary) { LabeledField( L10N.CacheFormat("#Principia_OrbitAnalyser_Elements_SiderealPeriod"), elements?.sidereal_period.FormatDuration()); LabeledField( L10N.CacheFormat("#Principia_OrbitAnalyser_Elements_NodalPeriod"), elements?.nodal_period.FormatDuration()); LabeledField( L10N.CacheFormat("#Principia_OrbitAnalyser_Elements_AnomalisticPeriod"), elements?.anomalistic_period.FormatDuration()); LabeledField( L10N.CacheFormat("#Principia_OrbitAnalyser_Elements_SemimajorAxis"), elements?.mean_semimajor_axis.FormatLengthInterval()); LabeledField( L10N.CacheFormat("#Principia_OrbitAnalyser_Elements_Eccentricity"), elements?.mean_eccentricity.FormatInterval()); LabeledField( L10N.CacheFormat("#Principia_OrbitAnalyser_Elements_Inclination"), elements?.mean_inclination.FormatAngleInterval()); LabeledField( L10N.CacheFormat( "#Principia_OrbitAnalyser_Elements_LongitudeOfAscendingNode"), elements?.mean_longitude_of_ascending_nodes.FormatAngleInterval()); LabeledField( L10N.CacheFormat("#Principia_OrbitAnalyser_Elements_NodalPrecession"), elements?.nodal_precession.FormatAngularFrequency()); string periapsis = L10N.CelestialString( "#Principia_OrbitAnalyser_Elements_Periapsis", new[] { primary }); string apoapsis = L10N.CelestialString( "#Principia_OrbitAnalyser_Elements_Apoapsis", new[] { primary }); LabeledField( L10N.CacheFormat( "#Principia_OrbitAnalyser_Elements_ArgumentOfPeriapsis", periapsis), elements?.mean_argument_of_periapsis.FormatAngleInterval()); LabeledField( L10N.CacheFormat( "#Principia_OrbitAnalyser_Elements_MeanPeriapsisAltitude", periapsis), elements?.mean_periapsis_distance.FormatLengthInterval(primary.Radius)); LabeledField( L10N.CacheFormat( "#Principia_OrbitAnalyser_Elements_MeanApoapsisAltitude", apoapsis), elements?.mean_apoapsis_distance.FormatLengthInterval(primary.Radius)); }
private static string TargetFrameName(Vessel target) { return(L10N.CelestialString( "#Principia_ReferenceFrameSelector_Name_Target", new [] { target.orbit.referenceBody })); }
private KSP.UI.Screens.Mapview.MapNode MakePoolNode() { var new_node = KSP.UI.Screens.Mapview.MapNode.Create( "apsis", // If we see this colour, something has gone wrong. XKCDColors.Pale, pixelSize: 32, hoverable: true, pinnable: true, blocksInput: true); new_node.OnClick += (KSP.UI.Screens.Mapview.MapNode node, Mouse.Buttons buttons) => { if (buttons == Mouse.Buttons.Left) { MapNodeProperties properties = properties_[node]; if (PlanetariumCamera.fetch.target != properties.associated_map_object) { PlanetariumCamera.fetch.SetTarget( properties.associated_map_object); } } }; new_node.OnUpdateVisible += (KSP.UI.Screens.Mapview.MapNode node, KSP.UI.Screens.Mapview.MapNode.IconData icon) => { icon.visible = properties_[node].visible; icon.color = properties_[node].colour; }; new_node.OnUpdateType += (KSP.UI.Screens.Mapview.MapNode node, KSP.UI.Screens.Mapview.MapNode.TypeData type) => { MapNodeProperties properties = properties_[node]; type.oType = properties.object_type; switch (properties.object_type) { case MapObject.ObjectType.PatchTransition: type.pType = KSP.UI.Screens.Mapview.MapNode.PatchTransitionNodeType. Impact; break; case MapObject.ObjectType.ApproachIntersect: type.aType = KSP.UI.Screens.Mapview.MapNode.ApproachNodeType. CloseApproachOwn; break; } }; new_node.OnUpdateCaption += (KSP.UI.Screens.Mapview.MapNode node, KSP.UI.Screens.Mapview.MapNode.CaptionData caption) => { var properties = properties_[node]; string source; switch (properties.source) { case NodeSource.FlightPlan: source = L10N.CacheFormat("#Principia_MapNode_Planned"); break; case NodeSource.Prediction: source = L10N.CacheFormat("#Principia_MapNode_Predicted"); break; default: throw Log.Fatal($"Unexpected node source {properties.source}"); } switch (properties.object_type) { case MapObject.ObjectType.Periapsis: case MapObject.ObjectType.Apoapsis: { CelestialBody celestial = properties.reference_frame.Centre(); Vector3d position = properties.world_position; double speed = properties.velocity.magnitude; caption.Header = L10N.CelestialString( properties.object_type == MapObject.ObjectType.Periapsis ? "#Principia_MapNode_PeriapsisHeader" : "#Principia_MapNode_ApoapsisHeader", new[] { celestial }, source, celestial.GetAltitude(position).FormatN(0)); caption.captionLine2 = L10N.CacheFormat("#Principia_MapNode_ApsisCaptionLine2", speed.FormatN(0)); break; } case MapObject.ObjectType.AscendingNode: case MapObject.ObjectType.DescendingNode: { string node_name = properties.object_type == MapObject.ObjectType.AscendingNode ? L10N.CacheFormat("#Principia_MapNode_AscendingNode") : L10N.CacheFormat("#Principia_MapNode_DescendingNode"); string plane = properties.reference_frame.ReferencePlaneDescription(); caption.Header = L10N.CacheFormat("#Principia_MapNode_NodeHeader", source, node_name, plane); caption.captionLine2 = L10N.CacheFormat( "#Principia_MapNode_NodeCaptionLine2", properties.velocity.z.FormatN(0)); break; } case MapObject.ObjectType.ApproachIntersect: { double separation = (properties.reference_frame.target.GetWorldPos3D() - properties.world_position).magnitude; double speed = properties.velocity.magnitude; caption.Header = L10N.CacheFormat("#Principia_MapNode_ApproachHeader", source, separation.FormatN(0)); caption.captionLine2 = L10N.CacheFormat( "#Principia_MapNode_ApproachCaptionLine2", speed.FormatN(0)); break; } case MapObject.ObjectType.PatchTransition: { CelestialBody celestial = properties.reference_frame.Centre(); caption.Header = L10N.CacheFormat("#Principia_MapNode_ImpactHeader", source, celestial.Name()); caption.captionLine1 = ""; caption.captionLine2 = ""; break; } } if (properties.object_type != MapObject.ObjectType.PatchTransition) { caption.captionLine1 = "T" + new PrincipiaTimeSpan( Planetarium.GetUniversalTime() - properties.time). Format(with_leading_zeroes: false, with_seconds: true); } }; new_node.OnUpdatePosition += (KSP.UI.Screens.Mapview.MapNode node) => ScaledSpace.LocalToScaledSpace(properties_[node].world_position); return(new_node); }
public static string OrbitDescription(CelestialBody primary, OrbitalElements?elements, OrbitRecurrence?recurrence, OrbitGroundTrack?ground_track, int?nodal_revolutions) { if (!elements.HasValue) { return(null); } string properties = ""; bool circular = false; bool equatorial = false; if (elements.Value.mean_eccentricity.max < 0.01) { circular = true; properties += L10N.CacheFormat( "#Principia_OrbitAnalyser_OrbitDescription_Circular"); } else if (elements.Value.mean_eccentricity.min > 0.5) { circular = true; properties += L10N.CacheFormat( "#Principia_OrbitAnalyser_OrbitDescription_HighlyElliptical"); } const double degree = Math.PI / 180; if (elements.Value.mean_inclination.max < 5 * degree || elements.Value.mean_inclination.min > 175 * degree) { equatorial = true; properties += L10N.CacheFormat( "#Principia_OrbitAnalyser_OrbitDescription_Equatorial"); } else if (elements.Value.mean_inclination.min > 80 * degree && elements.Value.mean_inclination.max < 100 * degree) { properties += L10N.CacheFormat("#Principia_OrbitAnalyser_OrbitDescription_Polar"); } else if (elements.Value.mean_inclination.min > 90 * degree) { properties += L10N.CacheFormat( "#Principia_OrbitAnalyser_OrbitDescription_Retrograde"); } if (recurrence.HasValue && ground_track.HasValue) { Interval ascending_longitudes = ground_track.Value.equatorial_crossings. longitudes_reduced_to_ascending_pass; Interval descending_longitudes = ground_track.Value.equatorial_crossings. longitudes_reduced_to_descending_pass; double drift = Math.Max( ascending_longitudes.max - ascending_longitudes.min, descending_longitudes.max - descending_longitudes.min); double revolutions_per_day = (double)recurrence.Value.number_of_revolutions / recurrence.Value.cto; double days = nodal_revolutions.Value / revolutions_per_day; // We ignore 0 drift as it means that there was only one pass, which is // insufficient to assess synchronicity. if (drift > 0 && drift / days < 0.1 * degree) { if (recurrence.Value.cto == 1) { switch (recurrence.Value.nuo) { case 1: if (circular && equatorial) { var stationary_string = L10N.CelestialStringOrNull( "#Principia_OrbitAnalyser_OrbitDescription_Stationary", new[] { primary }); if (stationary_string != null) { return(stationary_string); } properties = L10N.CacheFormat( "#Principia_OrbitAnalyser_OrbitDescription_Stationary"); } else { var synchronous_string = L10N.CelestialStringOrNull( "#Principia_OrbitAnalyser_OrbitDescription_Synchronous", new[] { primary }, properties); if (synchronous_string != null) { return(synchronous_string); } properties += L10N.CacheFormat( "#Principia_OrbitAnalyser_OrbitDescription_Synchronous"); } break; case 2: properties += L10N.CacheFormat( "#Principia_OrbitAnalyser_OrbitDescription_Semisynchronous"); break; default: break; } } } } return(L10N.CelestialString("#Principia_OrbitAnalyser_OrbitDescription", new[] { primary }, properties)); }