Here is the above code as text (no indentation):
public class Trajectory {
public enum Units { Mks, Fps };
public static readonly float degToRad = ( float ) Math.PI / 180;
public static readonly float radToDeg = 1 / degToRad;
public static readonly float metersToFeet = ( float ) ( 100 / 2.54 / 12 );
public static readonly float feetToMeters = 1 / metersToFeet;
public static readonly float gMks = 9.807f;
public static readonly float gFps = gMks * metersToFeet;
public readonly float g;
public readonly float h;
public readonly float v;
public readonly float dist;
public readonly float theta;
public readonly Units units;
public readonly int nSamples;
public readonly float a, b, c;
private readonly List<PointF> trajPoints = new List<PointF>();
private readonly PointF vertex;
// This static factory method returns an immutable instance of this class
// Internal fields are stored assuming the units specified in this invocation
// thetaDeg param is assumed to be in degrees and is converted to radians before being stored in instance.theta
public static Trajectory getInstance( float v, float h, float thetaDeg, Units units = Units.Fps, int nSamples = 200 ) {
return new Trajectory( v, h, thetaDeg, units, nSamples );
}
private Trajectory( float v, float h, float thetaDeg, Units units, int nSamples = 200 ) {
this.v = v;
this.h = h;
this.theta = thetaDeg * degToRad;
this.units = units;
this.nSamples = nSamples;
g = units == Units.Mks ? gMks : gFps;
// Calculate distance quadratic coefficients
float cosVal = ( float ) Math.Cos( theta );
a = -g / ( 2 * v * v * cosVal * cosVal );
b = ( float ) Math.Tan( theta );
c = h;
// Calculate max/throw distance
// Calculate x for which y = 0 in quadratic: y = ax^2 + bx + c using Quadratic Equation
dist = ( -b - ( float ) Math.Sqrt( b * b - 4 * a * c ) ) / ( 2 * a );
// Calculate vertex, the x-coord of vertex = -b/(2a)
float vertexX = -b / ( 2 * a );
float vertexY = a * vertexX * vertexX + b * vertexX + c;
vertex = new PointF( vertexX, vertexY );
// Calculate trajectory points
for ( int i = 0; i < nSamples; ++i ) {
float x = ( float ) i / ( float ) ( nSamples - 1 ) * ( float ) dist;
float y = ( float ) ( a * x * x + b * x + c );
trajPoints.Add( new PointF( x, y ) );
}
}
public PointF Vertex { get { return new PointF( vertex.X, vertex.Y ); } }
public PointF[] TrajPoints { get { return trajPoints.ToArray(); } } // Return array of PointF copies
private static string ptfToStr( PointF pt ) {
return "( " + pt.X.ToString( "0.00" ) + ", " + pt.Y.ToString( "0.00" ) + " )";
}
public string summStr() {
string unitStr = units == Units.Fps ? "f" : "m";
return "v0: " + v.ToString( "0." ) + " " + unitStr + "/s" +
" dist: " + dist.ToString( "0.0" ) + " " + unitStr +
" angle: " + theta * Trajectory.radToDeg + " deg";
}
public override string ToString() {
string distUnits = units == Units.Fps ? "feet" : "meters";
StringBuilder sb = new StringBuilder();
sb.AppendLine( "Trajectory object dump:" );
sb.AppendLine( " h: " + h + " " + distUnits );
sb.AppendLine( " v: " + v + " " + distUnits + "/sec" );
sb.AppendLine( " dist: " + dist + " " + distUnits );
sb.AppendLine( " vertex: " + vertex + " (" + distUnits + ")" );
sb.AppendLine( " theta: " + theta / degToRad );
sb.AppendLine( " nSamples: " + nSamples );
sb.AppendLine( " units: " + units.ToString() );
sb.AppendLine( " g: " + g + " " + distUnits + "/sec^2" );
sb.AppendLine( " a: " + a );
sb.AppendLine( " b: " + b );
sb.AppendLine( " c: " + c );
sb.AppendLine( " trajPoints:" );
for ( int i = 0; i < trajPoints.Count; ++i )
sb.AppendLine( " trajPoints[" + i + "]: " + ptfToStr( trajPoints[ i ] )+ " " + distUnits );
return sb.ToString();
}
}