Added relatives speed/velocity & units helper.
Added relatives speed/velocity & units helper.

--- a/KerbalEngineer/Editor/BuildAdvanced.cs
+++ b/KerbalEngineer/Editor/BuildAdvanced.cs
@@ -353,7 +353,7 @@
                 {
                     if (this.showAllStages || stage.deltaV > 0)
                     {
-                        GUILayout.Label(stage.mass.ToMass(false) + " / " + stage.totalMass.ToMass(), this.infoStyle);
+                        GUILayout.Label(Units.ToMass(stage.mass, stage.totalMass), this.infoStyle);
                     }
                 }
                 GUILayout.EndVertical();

--- a/KerbalEngineer/Extensions/DoubleExtensions.cs
+++ b/KerbalEngineer/Extensions/DoubleExtensions.cs
@@ -20,6 +20,8 @@
 #region Using Directives
 
 using System;
+
+using KerbalEngineer.Helpers;
 
 #endregion
 
@@ -44,100 +46,21 @@
             return value;
         }
 
-        /// <summary>
-        ///     Convert to ReadoutCategory formatted as acceleration.
-        /// </summary>
-        public static string ToAcceleration(this double value, bool showNotation = true)
+        public static string ToAcceleration(this double value)
         {
-            try
-            {
-                return showNotation ? value.ToString("N2") + "m/s²" : value.ToString("N2");
-            }
-            catch (Exception ex)
-            {
-                Logger.Exception(ex);
-                return "ERR";
-            }
+            return Units.ToAcceleration(value);
         }
 
-        /// <summary>
-        ///     Convert to ReadoutCategory formatted as an angle.
-        /// </summary>
-        public static string ToAngle(this double value, string format = "F3")
+        public static string ToAngle(this double value)
         {
-            try
-            {
-                return value.ToString(format) + "°";
-            }
-            catch (Exception ex)
-            {
-                Logger.Exception(ex, "DoubleExtentions->ToAngle");
-                return "ERR";
-            }
+            return Units.ToAngle(value);
         }
 
-        /// <summary>
-        ///     Convert to ReadoutCategory formatted as a distance.
-        /// </summary>
-        public static string ToDistance(this double value, string format = "N1")
+        public static string ToDistance(this double value)
         {
-            try
-            {
-                var negative = value < 0;
-
-                if (negative)
-                {
-                    value = -value;
-                }
-
-                if (value < 1000000.0f)
-                {
-                    if (value < 1.0f)
-                    {
-                        value *= 1000.0f;
-
-                        if (negative)
-                        {
-                            value = -value;
-                        }
-                        return value.ToString(format) + "mm";
-                    }
-
-                    if (negative)
-                    {
-                        value = -value;
-                    }
-                    return value.ToString(format) + "m";
-                }
-
-                value /= 1000.0f;
-                if (value >= 1000000.0f)
-                {
-                    value /= 1000.0f;
-
-                    if (negative)
-                    {
-                        value = -value;
-                    }
-                    return value.ToString(format) + "Mm";
-                }
-
-                if (negative)
-                {
-                    value = -value;
-                }
-                return value.ToString(format) + "km";
-            }
-            catch (Exception ex)
-            {
-                Logger.Exception(ex, "DoubleExtentions->ToDistance");
-                return "ERR";
-            }
+            return Units.ToDistance(value);
         }
 
-        /// <summary>
-        ///     Convert to a single precision floating point number.
-        /// </summary>
         public static float ToFloat(this double value)
         {
             try
@@ -151,43 +74,16 @@
             }
         }
 
-        /// <summary>
-        ///     Convert to ReadoutCategory formatted as a force.
-        /// </summary>
-        public static string ToForce(this double value, bool showNotation = true)
+        public static string ToForce(this double value)
         {
-            try
-            {
-                var format = (value < 100000) ? (value < 10000) ? (value < 100) ? "N3" : "N2" : "N1" : "N0";
-                return showNotation ? value.ToString(format) + "kN" : value.ToString(format);
-            }
-            catch (Exception ex)
-            {
-                Logger.Exception(ex, "DoubleExtentions->ToForce");
-                return "ERR";
-            }
+            return Units.ToForce(value);
         }
 
-        /// <summary>
-        ///     Convert to a ReadoutCategory formatted as a mass.
-        /// </summary>
-        public static string ToMass(this double value, bool showNotation = true)
+        public static string ToMass(this double value)
         {
-            try
-            {
-                value *= 1000;
-                return showNotation ? value.ToString("N0") + "kg" : value.ToString("N0");
-            }
-            catch (Exception ex)
-            {
-                Logger.Exception(ex, "DoubleExtentions->ToMass");
-                return "ERR";
-            }
+            return Units.ToMass(value);
         }
 
-        /// <summary>
-        ///     Convert to ReadoutCategory formatted as a rate.
-        /// </summary>
         public static string ToRate(this double value)
         {
             try
@@ -201,20 +97,9 @@
             }
         }
 
-        /// <summary>
-        ///     Convert to ReadoutCategory formatted as a speed.
-        /// </summary>
-        public static string ToSpeed(this double value, bool showNotation = true)
+        public static string ToSpeed(this double value)
         {
-            try
-            {
-                return showNotation ? value.ToString("N2") + "m/s" : value.ToString("N2");
-            }
-            catch (Exception ex)
-            {
-                Logger.Exception(ex, "DoubleExtentions->ToSpeed");
-                return "ERR";
-            }
+            return Units.ToSpeed(value);
         }
 
         #endregion

--- a/KerbalEngineer/Extensions/OrbitExtensions.cs
+++ b/KerbalEngineer/Extensions/OrbitExtensions.cs
@@ -20,6 +20,8 @@
 #region Using Directives
 
 using System;
+
+using KerbalEngineer.Helpers;
 
 using UnityEngine;
 
@@ -54,7 +56,7 @@
                 return 0.0;
             }
 
-            var angle = AngleBetweenVectors(orbit.getRelativePositionAtUT(Planetarium.GetUniversalTime()),
+            var angle = AngleHelper.GetAngleBetweenVectors(orbit.getRelativePositionAtUT(Planetarium.GetUniversalTime()),
                                             Vector3d.Exclude(orbit.GetOrbitNormal(), orbit.referenceBody.orbit.getRelativePositionAtUT(Planetarium.GetUniversalTime())));
 
             angle = (angle + 90.0).ClampTo(0.0, 360.0);
@@ -69,7 +71,7 @@
                 return 0.0;
             }
 
-            var angle = AngleBetweenVectors(orbit.getRelativePositionAtUT(Planetarium.GetUniversalTime()),
+            var angle = AngleHelper.GetAngleBetweenVectors(orbit.getRelativePositionAtUT(Planetarium.GetUniversalTime()),
                                             Vector3d.Exclude(orbit.GetOrbitNormal(), orbit.referenceBody.orbit.getRelativePositionAtUT(Planetarium.GetUniversalTime())));
 
             angle = (angle - 90.0).ClampTo(0.0, 360.0);
@@ -90,8 +92,8 @@
         public static double GetPhaseAngle(this Orbit orbit, Orbit target)
         {
             return orbit.inclination <= 90.0
-                ? AngleBetweenVectors(orbit.pos, Vector3d.Exclude(orbit.GetOrbitNormal(), target.pos))
-                : AngleBetweenVectors(Vector3d.Exclude(orbit.GetOrbitNormal(), target.pos), orbit.pos);
+                ? AngleHelper.GetAngleBetweenVectors(orbit.pos, Vector3d.Exclude(orbit.GetOrbitNormal(), target.pos))
+                : AngleHelper.GetAngleBetweenVectors(Vector3d.Exclude(orbit.GetOrbitNormal(), target.pos), orbit.pos);
         }
 
         public static double GetRelativeInclination(this Orbit orbit, Orbit target)
@@ -136,22 +138,5 @@
         }
 
         #endregion
-
-        #region Methods: private
-
-        private static double AngleBetweenVectors(Vector3d vector1, Vector3d vector2)
-        {
-            var angle = Vector3d.Angle(vector1, vector2);
-            var rotated = QuaternionD.AngleAxis(90.0, Vector3d.forward) * vector1;
-
-            if (Vector3d.Angle(rotated, vector2) > 90.0)
-            {
-                angle = 360.0 - angle;
-            }
-
-            return angle;
-        }
-
-        #endregion
     }
 }

--- a/KerbalEngineer/Flight/Readouts/Orbital/SemiMajorAxis.cs
+++ b/KerbalEngineer/Flight/Readouts/Orbital/SemiMajorAxis.cs
@@ -19,7 +19,7 @@
 
 #region Using Directives
 
-using KerbalEngineer.Extensions;
+using KerbalEngineer.Helpers;
 
 #endregion
 
@@ -43,7 +43,7 @@
 
         public override void Draw()
         {
-            this.DrawLine(FlightGlobals.ship_orbit.semiMajorAxis.ToDistance("N3"));
+            this.DrawLine(Units.ToDistance(FlightGlobals.ship_orbit.semiMajorAxis, 3));
         }
 
         #endregion

--- a/KerbalEngineer/Flight/Readouts/Orbital/SemiMinorAxis.cs
+++ b/KerbalEngineer/Flight/Readouts/Orbital/SemiMinorAxis.cs
@@ -19,7 +19,7 @@
 
 #region Using Directives
 
-using KerbalEngineer.Extensions;
+using KerbalEngineer.Helpers;
 
 #endregion
 
@@ -43,7 +43,7 @@
 
         public override void Draw()
         {
-            this.DrawLine(FlightGlobals.ship_orbit.semiMinorAxis.ToDistance("N3"));
+            this.DrawLine(Units.ToDistance(FlightGlobals.ship_orbit.semiMinorAxis, 3));
         }
 
         #endregion

--- a/KerbalEngineer/Flight/Readouts/ReadoutLibrary.cs
+++ b/KerbalEngineer/Flight/Readouts/ReadoutLibrary.cs
@@ -124,6 +124,8 @@
                 readouts.Add(new TargetSelector());
                 readouts.Add(new PhaseAngle());
                 readouts.Add(new InterceptAngle());
+                readouts.Add(new RelativeVelocity());
+                readouts.Add(new RelativeSpeed());
                 readouts.Add(new RelativeInclination());
                 readouts.Add(new TimeToRelativeAscendingNode());
                 readouts.Add(new TimeToRelativeDescendingNode());

--- /dev/null
+++ b/KerbalEngineer/Flight/Readouts/Rendezvous/RelativeSpeed.cs
@@ -1,1 +1,64 @@
+// 
+//     Kerbal Engineer Redux
+// 
+//     Copyright (C) 2014 CYBUTEK
+// 
+//     This program is free software: you can redistribute it and/or modify
+//     it under the terms of the GNU General Public License as published by
+//     the Free Software Foundation, either version 3 of the License, or
+//     (at your option) any later version.
+// 
+//     This program is distributed in the hope that it will be useful,
+//     but WITHOUT ANY WARRANTY; without even the implied warranty of
+//     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//     GNU General Public License for more details.
+// 
+//     You should have received a copy of the GNU General Public License
+//     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+// 
 
+#region Using Directives
+
+using KerbalEngineer.Extensions;
+
+#endregion
+
+namespace KerbalEngineer.Flight.Readouts.Rendezvous
+{
+    public class RelativeSpeed : ReadoutModule
+    {
+        #region Constructors
+
+        public RelativeSpeed()
+        {
+            this.Name = "Relative Speed";
+            this.Category = ReadoutCategory.GetCategory("Rendezvous");
+            this.HelpString = "Shows the difference in orbital speed between your vessel and the target object.";
+            this.IsDefault = false;
+        }
+
+        #endregion
+
+        #region Methods: public
+
+        public override void Draw()
+        {
+            if (RendezvousProcessor.ShowDetails)
+            {
+                this.DrawLine(RendezvousProcessor.RelativeSpeed.ToSpeed());
+            }
+        }
+
+        public override void Reset()
+        {
+            FlightEngineerCore.Instance.AddUpdatable(RendezvousProcessor.Instance);
+        }
+
+        public override void Update()
+        {
+            RendezvousProcessor.RequestUpdate();
+        }
+
+        #endregion
+    }
+}

--- /dev/null
+++ b/KerbalEngineer/Flight/Readouts/Rendezvous/RelativeVelocity.cs
@@ -1,1 +1,64 @@
+// 
+//     Kerbal Engineer Redux
+// 
+//     Copyright (C) 2014 CYBUTEK
+// 
+//     This program is free software: you can redistribute it and/or modify
+//     it under the terms of the GNU General Public License as published by
+//     the Free Software Foundation, either version 3 of the License, or
+//     (at your option) any later version.
+// 
+//     This program is distributed in the hope that it will be useful,
+//     but WITHOUT ANY WARRANTY; without even the implied warranty of
+//     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//     GNU General Public License for more details.
+// 
+//     You should have received a copy of the GNU General Public License
+//     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+// 
 
+#region Using Directives
+
+using KerbalEngineer.Extensions;
+
+#endregion
+
+namespace KerbalEngineer.Flight.Readouts.Rendezvous
+{
+    public class RelativeVelocity : ReadoutModule
+    {
+        #region Constructors
+
+        public RelativeVelocity()
+        {
+            this.Name = "Relative Velocity";
+            this.Category = ReadoutCategory.GetCategory("Rendezvous");
+            this.HelpString = "Shows the relative orbital velocity between your vessel and the target object.";
+            this.IsDefault = false;
+        }
+
+        #endregion
+
+        #region Methods: public
+
+        public override void Draw()
+        {
+            if (RendezvousProcessor.ShowDetails)
+            {
+                this.DrawLine(RendezvousProcessor.RelativeVelocity.ToSpeed());
+            }
+        }
+
+        public override void Reset()
+        {
+            FlightEngineerCore.Instance.AddUpdatable(RendezvousProcessor.Instance);
+        }
+
+        public override void Update()
+        {
+            RendezvousProcessor.RequestUpdate();
+        }
+
+        #endregion
+    }
+}

--- a/KerbalEngineer/Flight/Readouts/Rendezvous/RendezvousProcessor.cs
+++ b/KerbalEngineer/Flight/Readouts/Rendezvous/RendezvousProcessor.cs
@@ -22,6 +22,7 @@
 using System;
 
 using KerbalEngineer.Extensions;
+using KerbalEngineer.Helpers;
 
 using UnityEngine;
 
@@ -31,21 +32,9 @@
 {
     public class RendezvousProcessor : IUpdatable, IUpdateRequest
     {
-        #region Instance
+        #region Fields
 
         private static readonly RendezvousProcessor instance = new RendezvousProcessor();
-
-        /// <summary>
-        ///     Gets the current instance of the rendezvous processor.
-        /// </summary>
-        public static RendezvousProcessor Instance
-        {
-            get { return instance; }
-        }
-
-        #endregion
-
-        #region Fields
 
         private Orbit originOrbit;
         private Orbit targetOrbit;
@@ -55,24 +44,92 @@
         #region Properties
 
         /// <summary>
+        ///     Gets the target's altitude above its reference body.
+        /// </summary>
+        public static double AltitudeSeaLevel { get; private set; }
+
+        /// <summary>
+        ///     Gets the angle from the origin position to the ascending node.
+        /// </summary>
+        public static double AngleToAscendingNode { get; private set; }
+
+        /// <summary>
+        ///     Gets the angle from the origin position to the descending node.
+        /// </summary>
+        public static double AngleToDescendingNode { get; private set; }
+
+        /// <summary>
+        ///     Gets the target's apoapsis above its reference body.
+        /// </summary>
+        public static double ApoapsisHeight { get; private set; }
+
+        /// <summary>
+        ///     Gets the distance from the origin position to the target position.
+        /// </summary>
+        public static double Distance { get; private set; }
+
+        /// <summary>
+        ///     Gets the current instance of the rendezvous processor.
+        /// </summary>
+        public static RendezvousProcessor Instance
+        {
+            get { return instance; }
+        }
+
+        /// <summary>
+        ///     Gets the difference in angle from the origin position to where it is most efficient to burn for an encounter.
+        /// </summary>
+        public static double InterceptAngle { get; private set; }
+
+        /// <summary>
+        ///     Gets the orbital period of the target orbit.
+        /// </summary>
+        public static double OrbitalPeriod { get; private set; }
+
+        /// <summary>
+        ///     Gets the target's periapsis above its reference body.
+        /// </summary>
+        public static double PeriapsisHeight { get; private set; }
+
+        /// <summary>
+        ///     Gets the difference in angle from the origin position to the target position based on a common reference.
+        /// </summary>
+        public static double PhaseAngle { get; private set; }
+
+        /// <summary>
+        ///     Gets the angular difference between the origin and target orbits.
+        /// </summary>
+        public static double RelativeInclination { get; private set; }
+
+        /// <summary>
+        ///     Gets the relative orbital velocity between the vessel and target.
+        /// </summary>
+        public static double RelativeVelocity { get; private set; }
+
+        /// <summary>
+        ///     Gets the relative orbital speed between the vessel and target.
+        /// </summary>
+        public static double RelativeSpeed { get; private set; }
+
+        /// <summary>
+        ///     Gets the semi-major axis of the target orbit.
+        /// </summary>
+        public static double SemiMajorAxis { get; private set; }
+
+        /// <summary>
+        ///     Gets the semi-minor axis of the target orbit.
+        /// </summary>
+        public static double SemiMinorAxis { get; private set; }
+
+        /// <summary>
         ///     Gets whether the details are ready to be shown.
         /// </summary>
         public static bool ShowDetails { get; private set; }
 
         /// <summary>
-        ///     Gets the difference in angle from the origin position to the target position based on a common reference.
-        /// </summary>
-        public static double PhaseAngle { get; private set; }
-
-        /// <summary>
-        ///     Gets the difference in angle from the origin position to where it is most efficient to burn for an encounter.
-        /// </summary>
-        public static double InterceptAngle { get; private set; }
-
-        /// <summary>
-        ///     Gets the angular difference between the origin and target orbits.
-        /// </summary>
-        public static double RelativeInclination { get; private set; }
+        ///     Gets the target's time to apoapsis.
+        /// </summary>
+        public static double TimeToApoapsis { get; private set; }
 
         /// <summary>
         ///     Gets the time it will take to reach the ascending node.
@@ -85,63 +142,26 @@
         public static double TimeToDescendingNode { get; private set; }
 
         /// <summary>
-        ///     Gets the angle from the origin position to the ascending node.
-        /// </summary>
-        public static double AngleToAscendingNode { get; private set; }
-
-        /// <summary>
-        ///     Gets the angle from the origin position to the descending node.
-        /// </summary>
-        public static double AngleToDescendingNode { get; private set; }
-
-        /// <summary>
-        ///     Gets the target's altitude above its reference body.
-        /// </summary>
-        public static double AltitudeSeaLevel { get; private set; }
-
-        /// <summary>
-        ///     Gets the target's apoapsis above its reference body.
-        /// </summary>
-        public static double ApoapsisHeight { get; private set; }
-
-        /// <summary>
-        ///     Gets the target's periapsis above its reference body.
-        /// </summary>
-        public static double PeriapsisHeight { get; private set; }
-
-        /// <summary>
-        ///     Gets the target's time to apoapsis.
-        /// </summary>
-        public static double TimeToApoapsis { get; private set; }
-
-        /// <summary>
         ///     Gets the target's time to periapsis.
         /// </summary>
         public static double TimeToPeriapsis { get; private set; }
 
         /// <summary>
-        ///     Gets the distance from the origin position to the target position.
-        /// </summary>
-        public static double Distance { get; private set; }
-
-        /// <summary>
-        ///     Gets the orbital period of the target orbit.
-        /// </summary>
-        public static double OrbitalPeriod { get; private set; }
-
-        /// <summary>
-        ///     Gets the semi-major axis of the target orbit.
-        /// </summary>
-        public static double SemiMajorAxis { get; private set; }
-
-        /// <summary>
-        ///     Gets the semi-minor axis of the target orbit.
-        /// </summary>
-        public static double SemiMinorAxis { get; private set; }
-
-        #endregion
-
-        #region IUpdatable Members
+        ///     Gets and sets whether the updatable object should be updated.
+        /// </summary>
+        public bool UpdateRequested { get; set; }
+
+        #endregion
+
+        #region Methods: public
+
+        /// <summary>
+        ///     Request and update to calculate the details.
+        /// </summary>
+        public static void RequestUpdate()
+        {
+            instance.UpdateRequested = true;
+        }
 
         /// <summary>
         ///     Updates the details by recalculating if requested.
@@ -162,12 +182,14 @@
                 : FlightGlobals.ship_orbit.referenceBody.orbit;
 
             RelativeInclination = this.originOrbit.GetRelativeInclination(this.targetOrbit);
+            RelativeVelocity = FlightGlobals.ship_tgtSpeed;
+            RelativeSpeed = FlightGlobals.ship_obtSpeed - FlightGlobals.ActiveVessel.targetObject.GetObtVelocity().magnitude;
             PhaseAngle = this.originOrbit.GetPhaseAngle(this.targetOrbit);
             InterceptAngle = this.CalcInterceptAngle();
             TimeToAscendingNode = this.originOrbit.GetTimeToVector(this.GetAscendingNode());
             TimeToDescendingNode = this.originOrbit.GetTimeToVector(this.GetDescendingNode());
             AngleToAscendingNode = this.originOrbit.GetAngleToVector(this.GetAscendingNode());
-            AngleToDescendingNode =this.originOrbit.GetAngleToVector(this.GetDescendingNode());
+            AngleToDescendingNode = this.originOrbit.GetAngleToVector(this.GetDescendingNode());
             AltitudeSeaLevel = this.targetOrbit.altitude;
             ApoapsisHeight = this.targetOrbit.ApA;
             PeriapsisHeight = this.targetOrbit.PeA;
@@ -182,24 +204,7 @@
 
         #endregion
 
-        #region IUpdateRequest Members
-
-        /// <summary>
-        ///     Gets and sets whether the updatable object should be updated.
-        /// </summary>
-        public bool UpdateRequested { get; set; }
-
-        #endregion
-
-        /// <summary>
-        ///     Request and update to calculate the details.
-        /// </summary>
-        public static void RequestUpdate()
-        {
-            instance.UpdateRequested = true;
-        }
-
-        #region Calculations
+        #region Methods: private
 
         private double CalcInterceptAngle()
         {

--- a/KerbalEngineer/Flight/Readouts/Rendezvous/SemiMajorAxis.cs
+++ b/KerbalEngineer/Flight/Readouts/Rendezvous/SemiMajorAxis.cs
@@ -21,7 +21,7 @@
 
 using System;
 
-using KerbalEngineer.Extensions;
+using KerbalEngineer.Helpers;
 
 #endregion
 
@@ -47,7 +47,7 @@
         {
             if (RendezvousProcessor.ShowDetails)
             {
-                this.DrawLine(RendezvousProcessor.SemiMajorAxis.ToDistance("N3"));
+                this.DrawLine(Units.ToDistance(RendezvousProcessor.SemiMajorAxis, 3));
             }
         }
 

--- a/KerbalEngineer/Flight/Readouts/Rendezvous/SemiMinorAxis.cs
+++ b/KerbalEngineer/Flight/Readouts/Rendezvous/SemiMinorAxis.cs
@@ -21,7 +21,7 @@
 
 using System;
 
-using KerbalEngineer.Extensions;
+using KerbalEngineer.Helpers;
 
 #endregion
 
@@ -47,7 +47,7 @@
         {
             if (RendezvousProcessor.ShowDetails)
             {
-                this.DrawLine(RendezvousProcessor.SemiMajorAxis.ToDistance("N3"));
+                this.DrawLine(Units.ToDistance(RendezvousProcessor.SemiMajorAxis, 3));
             }
         }
 

--- a/KerbalEngineer/Flight/Readouts/Surface/Latitude.cs
+++ b/KerbalEngineer/Flight/Readouts/Surface/Latitude.cs
@@ -19,7 +19,7 @@
 
 #region Using Directives
 
-using KerbalEngineer.Extensions;
+using KerbalEngineer.Helpers;
 
 #endregion
 
@@ -27,6 +27,8 @@
 {
     public class Latitude : ReadoutModule
     {
+        #region Constructors
+
         public Latitude()
         {
             this.Name = "Latitude";
@@ -35,9 +37,15 @@
             this.IsDefault = true;
         }
 
+        #endregion
+
+        #region Methods: public
+
         public override void Draw()
         {
-            this.DrawLine(FlightGlobals.ship_latitude.ToAngle());
+            this.DrawLine(Units.ToAngle(FlightGlobals.ship_latitude));
         }
+
+        #endregion
     }
 }

--- a/KerbalEngineer/Flight/Readouts/Surface/Longitude.cs
+++ b/KerbalEngineer/Flight/Readouts/Surface/Longitude.cs
@@ -19,7 +19,7 @@
 
 #region Using Directives
 
-using KerbalEngineer.Extensions;
+using KerbalEngineer.Helpers;
 
 #endregion
 
@@ -27,6 +27,8 @@
 {
     public class Longitude : ReadoutModule
     {
+        #region Constructors
+
         public Longitude()
         {
             this.Name = "Longitude";
@@ -35,9 +37,15 @@
             this.IsDefault = true;
         }
 
+        #endregion
+
+        #region Methods: public
+
         public override void Draw()
         {
-            this.DrawLine(FlightGlobals.ship_longitude.ToAngle());
+            this.DrawLine(Units.ToAngle(FlightGlobals.ship_longitude));
         }
+
+        #endregion
     }
 }

--- a/KerbalEngineer/Flight/Readouts/Surface/Slope.cs
+++ b/KerbalEngineer/Flight/Readouts/Surface/Slope.cs
@@ -21,7 +21,7 @@
 
 using System;
 
-using KerbalEngineer.Extensions;
+using KerbalEngineer.Helpers;
 
 using UnityEngine;
 
@@ -31,6 +31,8 @@
 {
     public class Slope : ReadoutModule
     {
+        #region Constructors
+
         public Slope()
         {
             this.Name = "Slope";
@@ -39,10 +41,18 @@
             this.IsDefault = true;
         }
 
+        #endregion
+
+        #region Methods: public
+
         public override void Draw()
         {
             this.DrawLine(this.GetSlopeAngleAndHeading());
         }
+
+        #endregion
+
+        #region Methods: private
 
         private string GetSlopeAngleAndHeading()
         {
@@ -66,7 +76,7 @@
                         raddotnorm = 0.0;
                     }
                     var slope = Math.Acos(raddotnorm) * 180 / Math.PI;
-                    result = slope.ToAngle("F1");
+                    result = Units.ToAngle(slope, 1);
                     if (slope < 0.05)
                     {
                         result += " @ ---°";
@@ -83,7 +93,7 @@
                         {
                             direction = 360 - direction;
                         }
-                        result += " @ " + direction.ToAngle("F0");
+                        result += " @ " + Units.ToAngle(direction, 1);
                     }
                 }
 
@@ -95,5 +105,7 @@
                 return "--° @ ---°";
             }
         }
+
+        #endregion
     }
 }

--- a/KerbalEngineer/Flight/Readouts/Vessel/Acceleration.cs
+++ b/KerbalEngineer/Flight/Readouts/Vessel/Acceleration.cs
@@ -22,6 +22,7 @@
 using System.Diagnostics;
 
 using KerbalEngineer.Extensions;
+using KerbalEngineer.Helpers;
 
 using UnityEngine;
 
@@ -50,7 +51,7 @@
         {
             if (SimulationProcessor.ShowDetails)
             {
-                this.DrawLine((SimulationProcessor.LastStage.actualThrust / SimulationProcessor.LastStage.totalMass).ToAcceleration(false) + " / " + (SimulationProcessor.LastStage.thrust / SimulationProcessor.LastStage.totalMass).ToAcceleration());
+                this.DrawLine(Units.ToAcceleration(SimulationProcessor.LastStage.actualThrust / SimulationProcessor.LastStage.totalMass, SimulationProcessor.LastStage.thrust / SimulationProcessor.LastStage.totalMass));
             }
             else if (this.showing)
             {

--- a/KerbalEngineer/Flight/Readouts/Vessel/Mass.cs
+++ b/KerbalEngineer/Flight/Readouts/Vessel/Mass.cs
@@ -19,8 +19,7 @@
 
 #region Using Directives
 
-using KerbalEngineer.Extensions;
-using KerbalEngineer.VesselSimulator;
+using KerbalEngineer.Helpers;
 
 #endregion
 
@@ -28,7 +27,13 @@
 {
     public class Mass : ReadoutModule
     {
+        #region Fields
+
         private bool showing;
+
+        #endregion
+
+        #region Constructors
 
         public Mass()
         {
@@ -38,16 +43,15 @@
             this.IsDefault = true;
         }
 
-        public override void Update()
-        {
-            SimulationProcessor.RequestUpdate();
-        }
+        #endregion
+
+        #region Methods: public
 
         public override void Draw()
         {
             if (SimulationProcessor.ShowDetails)
             {
-                this.DrawLine(SimulationProcessor.LastStage.mass.ToMass(false) + " / " + SimulationProcessor.LastStage.totalMass.ToMass());
+                this.DrawLine(Units.ToMass(SimulationProcessor.LastStage.mass, SimulationProcessor.LastStage.totalMass));
             }
             else if (this.showing)
             {
@@ -60,5 +64,12 @@
         {
             FlightEngineerCore.Instance.AddUpdatable(SimulationProcessor.Instance);
         }
+
+        public override void Update()
+        {
+            SimulationProcessor.RequestUpdate();
+        }
+
+        #endregion
     }
 }

--- a/KerbalEngineer/Flight/Readouts/Vessel/Thrust.cs
+++ b/KerbalEngineer/Flight/Readouts/Vessel/Thrust.cs
@@ -19,7 +19,7 @@
 
 #region Using Directives
 
-using KerbalEngineer.Extensions;
+using KerbalEngineer.Helpers;
 
 #endregion
 
@@ -27,7 +27,13 @@
 {
     public class Thrust : ReadoutModule
     {
+        #region Fields
+
         private bool showing;
+
+        #endregion
+
+        #region Constructors
 
         public Thrust()
         {
@@ -37,16 +43,15 @@
             this.IsDefault = true;
         }
 
-        public override void Update()
-        {
-            SimulationProcessor.RequestUpdate();
-        }
+        #endregion
+
+        #region Methods: public
 
         public override void Draw()
         {
             if (SimulationProcessor.ShowDetails)
             {
-                this.DrawLine(SimulationProcessor.LastStage.actualThrust.ToForce(false) + " / " + SimulationProcessor.LastStage.thrust.ToForce());
+                this.DrawLine(Units.ToForce(SimulationProcessor.LastStage.actualThrust, SimulationProcessor.LastStage.thrust));
             }
             else if (this.showing)
             {
@@ -59,5 +64,12 @@
         {
             FlightEngineerCore.Instance.AddUpdatable(SimulationProcessor.Instance);
         }
+
+        public override void Update()
+        {
+            SimulationProcessor.RequestUpdate();
+        }
+
+        #endregion
     }
 }

--- /dev/null
+++ b/KerbalEngineer/Helpers/AngleHelper.cs
@@ -1,1 +1,47 @@
+// 
+//     Kerbal Engineer Redux
+// 
+//     Copyright (C) 2014 CYBUTEK
+// 
+//     This program is free software: you can redistribute it and/or modify
+//     it under the terms of the GNU General Public License as published by
+//     the Free Software Foundation, either version 3 of the License, or
+//     (at your option) any later version.
+// 
+//     This program is distributed in the hope that it will be useful,
+//     but WITHOUT ANY WARRANTY; without even the implied warranty of
+//     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//     GNU General Public License for more details.
+// 
+//     You should have received a copy of the GNU General Public License
+//     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+// 
 
+#region Using Directives
+
+using UnityEngine;
+
+#endregion
+
+namespace KerbalEngineer.Helpers
+{
+    public static class AngleHelper
+    {
+        #region Methods: public
+
+        public static double GetAngleBetweenVectors(Vector3d vector1, Vector3d vector2)
+        {
+            var angle = Vector3d.Angle(vector1, vector2);
+            var rotated = QuaternionD.AngleAxis(90.0, Vector3d.forward) * vector1;
+
+            if (Vector3d.Angle(rotated, vector2) > 90.0)
+            {
+                angle = 360.0 - angle;
+            }
+
+            return angle;
+        }
+
+        #endregion
+    }
+}

--- /dev/null
+++ b/KerbalEngineer/Helpers/Units.cs
@@ -1,1 +1,115 @@
+// 
+//     Kerbal Engineer Redux
+// 
+//     Copyright (C) 2014 CYBUTEK
+// 
+//     This program is free software: you can redistribute it and/or modify
+//     it under the terms of the GNU General Public License as published by
+//     the Free Software Foundation, either version 3 of the License, or
+//     (at your option) any later version.
+// 
+//     This program is distributed in the hope that it will be useful,
+//     but WITHOUT ANY WARRANTY; without even the implied warranty of
+//     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//     GNU General Public License for more details.
+// 
+//     You should have received a copy of the GNU General Public License
+//     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+// 
 
+#region Using Directives
+
+using System;
+
+#endregion
+
+
+
+namespace KerbalEngineer.Helpers
+{
+    public static class Units
+    {
+        #region Methods: public
+
+        public static string ToAcceleration(double value, int decimals = 2)
+        {
+            return value.ToString("N" + decimals) + "m/s²";
+        }
+
+        public static string ToAcceleration(double value1, double value2, int decimals = 2)
+        {
+            return value1.ToString("N" + decimals) + " / " + value2.ToString("N" + decimals) + "m/s²";
+        }
+
+        public static string ToAngle(double value, int decimals = 5)
+        {
+            return value.ToString("F" + decimals) + "°";
+        }
+
+        public static string ToDistance(double value, int decimals = 1)
+        {
+            if (Math.Abs(value) < 1000000.0)
+            {
+                if (Math.Abs(value) < 10.0)
+                {
+                    value *= 100.0;
+                    if (Math.Abs(value) < 100.0)
+                    {
+                        value *= 10.0;
+                        return value.ToString("N" + decimals) + "mm";
+                    }
+                    return value.ToString("N" + decimals) + "cm";
+                }
+                return value.ToString("N" + decimals) + "m";
+            }
+
+            value /= 1000.0;
+            if (Math.Abs(value) >= 1000000.0)
+            {
+                value /= 1000.0;
+                return value.ToString("N" + decimals) + "Mm";
+            }
+            return value.ToString("N" + decimals) + "km";
+        }
+
+        public static string ToForce(double value)
+        {
+            return value.ToString((value < 100000.0) ? (value < 10000.0) ? (value < 100.0) ? "N3" : "N2" : "N1" : "N0") + "kN";
+        }
+
+        public static string ToForce(double value1, double value2)
+        {
+            var format = (value1 < 100000.0) ? (value1 < 10000.0) ? (value1 < 100.0) ? "N3" : "N2" : "N1" : "N0";
+            return value1.ToString(format) + " / " + value2.ToString(format) + "kN";
+        }
+
+        public static string ToMass(double value, int decimals = 0)
+        {
+            value *= 1000.0;
+            return value.ToString("N" + decimals) + "kg";
+        }
+
+        public static string ToMass(double value1, double value2, int decimals = 0)
+        {
+            value1 *= 1000.0;
+            value2 *= 1000.0;
+            return value1.ToString("N" + decimals) + " / " + value2.ToString("N" + decimals) + "kg";
+        }
+
+        public static string ToSpeed(double value, int decimals = 2)
+        {
+            if (Math.Abs(value) < 1.0)
+            {
+                return (value * 1000.0).ToString("N" + decimals) + "mm/s";
+            }
+            return value.ToString("N" + decimals) + "m/s";
+        }
+
+        public static string ToTime(double value)
+        {
+            return TimeFormatter.ConvertToString(value);
+        }
+
+        #endregion
+    }
+}

--- a/KerbalEngineer/KerbalEngineer.csproj
+++ b/KerbalEngineer/KerbalEngineer.csproj
@@ -77,6 +77,8 @@
     <Compile Include="Flight\Readouts\Orbital\TrueAnomaly.cs" />
     <Compile Include="Flight\Readouts\Orbital\TimeToEquatorialAscendingNode.cs" />
     <Compile Include="Flight\Readouts\Orbital\TimeToEquatorialDescendingNode.cs" />
+    <Compile Include="Flight\Readouts\Rendezvous\RelativeSpeed.cs" />
+    <Compile Include="Flight\Readouts\Rendezvous\RelativeVelocity.cs" />
     <Compile Include="Flight\Readouts\Rendezvous\SemiMinorAxis.cs" />
     <Compile Include="Flight\Readouts\Rendezvous\SemiMajorAxis.cs" />
     <Compile Include="Flight\Readouts\Rendezvous\TimeToRelativeDescendingNode.cs" />
@@ -92,6 +94,8 @@
     <Compile Include="Flight\Readouts\Vessel\Acceleration.cs" />
     <Compile Include="Flight\Presets\PresetLibrary.cs" />
     <Compile Include="GuiDisplaySize.cs" />
+    <Compile Include="Helpers\AngleHelper.cs" />
+    <Compile Include="Helpers\Units.cs" />
     <Compile Include="Helpers\TimeFormatter.cs" />
     <Compile Include="UIControls\DropDown.cs" />
     <Compile Include="Logger.cs" />

 Binary files a/Output/KerbalEngineer/KerbalEngineer.dll and b/Output/KerbalEngineer/KerbalEngineer.dll differ