private void drawApoapse(Graphics g, Orbit orbit) { float x, y; Tuple <double, double> XY = getXYfromTheta(Helper.deg2rad(180) + thetaZero, orbit); x = (float)XY.Item1; y = (float)XY.Item2; g.FillEllipse(apoBrush, x - 5, y - 5, 10, 10); g.DrawString(Math.Round(orbit.ApoapsisAltitude).ToString(), font, textBrush, x, y); }
private void drawAscDescNodes(Graphics g, Orbit orbit) { float x, y; Tuple <double, double> XY = getXYfromTheta(alphaZero, orbit); x = (float)XY.Item1; y = (float)XY.Item2; g.FillEllipse(NodeBrush, x - 5, y - 5, 10, 10); XY = getXYfromTheta(Helper.deg2rad(180) + alphaZero, orbit); x = (float)XY.Item1; y = (float)XY.Item2; g.FillEllipse(NodeBrush, x - 5, y - 5, 10, 10); }
private PointF[] screwInfillPoints(float x, float y, float size) { PointF[] path = new PointF[6]; float s = (float)((size / 2f) * Math.Sin(Helper.deg2rad(30))); float l = (float)((size / 2f) * Math.Cos(Helper.deg2rad(30))); path[0] = new PointF(x, y + (size / 2f)); path[1] = new PointF(x + s, y + (size / 2f) - l); path[2] = new PointF(x + size - s, y + (size / 2f) - l); path[3] = new PointF(x + size, y + (size / 2f)); path[4] = new PointF(x + size - s, y + (size / 2f) + l); path[5] = new PointF(x + s, y + (size / 2f) + l); return(path); }
private void drawSinglePointer(Graphics g) { // Pointer double scaler = (Height - 20) / (double)Math.Abs(scale1max - scale1min); float y = (float)((Height - 10) - (value1 * scaler)); float x = 3; float w = Width / 3; float a = 50; // Angle at "pointy" end PointF[] points = new PointF[4]; points[0] = new PointF(x + w, y); points[1] = new PointF(x, (float)(y + (w * Math.Sin(Helper.deg2rad(a / 2))))); points[2] = new PointF(x, (float)(y - (w * Math.Sin(Helper.deg2rad(a / 2))))); points[3] = new PointF(x + w, y); g.FillPolygon(pointerBrush, points); RectangleF Rect = new RectangleF(0, y - 1, 4, 2); g.FillRectangle(pointerBrush, Rect); }
public override void updateLocalElements(object sender, EventArgs e) { // Re-usable data variable for graph data List <List <KeyValuePair <double, double?> > > data = new List <List <KeyValuePair <double, double?> > >(); List <Plot.Type> types = new List <Plot.Type>(); int steps = 200; string tgtapo = form.dataStorage.getData("TGTAPO"); if (tgtapo == "") { tgtapo = "120000"; form.dataStorage.setData("TGTAPO", "120000"); } int.TryParse(tgtapo, out int apo); double mass = form.streamCollection.GetData(DataType.body_mass); if (mass == 0) { mass = 5.2915158e22; } double bodyrad = form.streamCollection.GetData(DataType.body_radius); if (bodyrad == 0) { bodyrad = 600000; } double distance = bodyrad + apo; double speed = Math.Sqrt((6.67408e-11 * mass) / distance); // Find inertial speed at the pad float rotPeriod = form.streamCollection.GetData(DataType.body_rotPeriod); if (rotPeriod == 0) { rotPeriod = 21600; } // If no period found, set to Kerbin-period double lat = 0; // TODO: Set to 0 now, add button to calibrate later // MAKE GUIDE(S) // TODO: THIS SHOULD MAYBE BE CALCULATED BY SOME METHOD double StaticSpeed = (2 * Math.PI * bodyrad * Math.Cos(Helper.deg2rad(lat))) / rotPeriod; double speedStep = (speed - StaticSpeed) / steps; double maxAngle = 40; double maxAnglePosition = 0.1; // position on the velocity axis of max angle. 0.0 - 1.0 double maxAngleSpeed = ((speed - StaticSpeed) * maxAnglePosition) + StaticSpeed; double a = (speed - StaticSpeed) * maxAnglePosition; // X-axis length double b = maxAngle; // Y-axis height double c = 0; // Y-axis offset double d = maxAngleSpeed; // X-axis offset List <KeyValuePair <double, double?> > middle = new List <KeyValuePair <double, double?> >(); List <KeyValuePair <double, double?> > middle2 = new List <KeyValuePair <double, double?> >(); List <KeyValuePair <double, double?> > tgt = new List <KeyValuePair <double, double?> >(); List <KeyValuePair <double, double?> > low = new List <KeyValuePair <double, double?> >(); List <KeyValuePair <double, double?> > low2 = new List <KeyValuePair <double, double?> >(); List <KeyValuePair <double, double?> > high = new List <KeyValuePair <double, double?> >(); List <KeyValuePair <double, double?> > high2 = new List <KeyValuePair <double, double?> >(); for (int i = 0; i <= steps; i++) { // ELLIPTIC CURVE int x = (int)(Math.Round(i * ((maxAngleSpeed - StaticSpeed) / steps)) + StaticSpeed); double?y = Math.Sqrt(Math.Pow(b, 2) * (1 - (Math.Pow(x - d, 2) / Math.Pow(a, 2)))) + c; if (i == 0) { y = 0; } middle.Add(new KeyValuePair <double, double?>(x, y)); low.Add(new KeyValuePair <double, double?>(x, y * 0.8)); high.Add(new KeyValuePair <double, double?>(x, y * 1.2)); // SMOOTHSTEP DOWN x = (int)(speed - (i * ((speed - maxAngleSpeed) / steps))); double t = (x - maxAngleSpeed) / (speed - maxAngleSpeed); double m0 = 1.5; double m1 = 0.5; double sx = ((Math.Pow(t, 3) - (2 * Math.Pow(t, 2)) + t) * m0) + ((-2 * Math.Pow(t, 3)) + (3 * Math.Pow(t, 2))) + ((Math.Pow(t, 3) - Math.Pow(t, 2)) * m1); double sy = (-2 * Math.Pow(t, 3)) + (3 * Math.Pow(t, 2)); x = (int)(speed - Math.Round(sx * (speed - maxAngleSpeed))); y = sy * maxAngle; middle2.Add(new KeyValuePair <double, double?>(x, y)); low2.Add(new KeyValuePair <double, double?>(x, y * 0.8)); high2.Add(new KeyValuePair <double, double?>(x, y * 1.2)); } // TARGET LINE tgt.Add(new KeyValuePair <double, double?>(speed, -2)); tgt.Add(new KeyValuePair <double, double?>(speed, 2)); data.Add(middle); types.Add(Plot.Type.LINE); data.Add(middle2); types.Add(Plot.Type.LINE); if (form.form.connected && form.form.krpc.CurrentGameScene == GameScene.Flight) { data.Add(chartData["FlightangleVelocity"]); types.Add(Plot.Type.CROSS); } else { // ADD EMPTY DATA data.Add(new List <KeyValuePair <double, double?> >()); types.Add(Plot.Type.CROSS); } data.Add(tgt); types.Add(Plot.Type.LINE); data.Add(low); types.Add(Plot.Type.LINE); data.Add(low2); types.Add(Plot.Type.LINE); data.Add(high); types.Add(Plot.Type.LINE); data.Add(high2); types.Add(Plot.Type.LINE); screenCharts[0].setData(data, types, false); screenCharts[0].maxX = (int)Math.Round(speed * 1.1f); }
private void MakeOrbitConstants(Graphics g, Orbit orbit, bool relativeToParent, double time, string debugstr, bool relativeREF) { float x, y; double alpha; double r; double REF = 0; // Degress from x-right double bodyInc; if (orbit.Body.Name == "Sun") { bodyInc = 0; } else { bodyInc = orbit.Body.Orbit.Inclination; if (relativeREF) { if (time != -1) { if (bodyInc > Helper.deg2rad(90) && bodyInc <= Helper.deg2rad(270)) { REF = 0 - orbit.Body.Orbit.LongitudeOfAscendingNode + orbit.Body.Orbit.ArgumentOfPeriapsis + orbit.Body.Orbit.TrueAnomalyAtUT(time); } else { REF = 0 - orbit.Body.Orbit.LongitudeOfAscendingNode - orbit.Body.Orbit.ArgumentOfPeriapsis - orbit.Body.Orbit.TrueAnomalyAtUT(time); } } else { if (bodyInc > Helper.deg2rad(90) && bodyInc <= Helper.deg2rad(270)) { REF = 0 - orbit.Body.Orbit.LongitudeOfAscendingNode + orbit.Body.Orbit.ArgumentOfPeriapsis + orbit.Body.Orbit.TrueAnomaly; } else { REF = 0 - orbit.Body.Orbit.LongitudeOfAscendingNode - orbit.Body.Orbit.ArgumentOfPeriapsis - orbit.Body.Orbit.TrueAnomaly; } } } } eccentricity = orbit.Eccentricity; inclination = orbit.Inclination; trueAnomaly = orbit.TrueAnomaly; bodyOrbit = orbit.Body.Orbit; if (eccentricity <= 0.00001) { // SET EVERYTHING TO 0 thetaZero = 0; thetaZeroNoREF = 0; alphaZero = 0; directrix = orbit.Periapsis; x = (float)((orbit.Periapsis * scaler) + graphCenterX); P1 = new PointF(x, (float)(graphCenterY + satY)); P2 = new PointF(-x, (float)(graphCenterY - satY)); } else { if (inclination > Helper.deg2rad(90) && inclination <= Helper.deg2rad(270)) { thetaZeroNoREF = 0 - orbit.LongitudeOfAscendingNode + orbit.ArgumentOfPeriapsis; // Rotation clockwise from x-direction (Right) of Apoapse thetaZero = REF + thetaZeroNoREF; alphaZero = REF - orbit.LongitudeOfAscendingNode; // Decending Node } else { thetaZeroNoREF = 0 - orbit.LongitudeOfAscendingNode - orbit.ArgumentOfPeriapsis; // Rotation counterclockwise from x-direction (Right) of Apoapse thetaZero = REF + thetaZeroNoREF; alphaZero = REF - orbit.LongitudeOfAscendingNode; // Decending Node } directrix = (orbit.Periapsis / eccentricity) + orbit.Periapsis; //Inclination point 1 alpha = alphaZero; r = (eccentricity * directrix) / (1 + (eccentricity * Math.Cos(alpha - thetaZero))); x = (float)((r * Math.Cos(alpha) * scaler) + graphCenterX + satX); y = (float)((r * Math.Sin(alpha) * scaler) + graphCenterY - satY); P1 = new PointF(x, y); //g.FillEllipse(burnBrush, x - 5, y - 5, 10, 10); //Inclination point 2 alpha = Helper.deg2rad(180) + alphaZero; r = (eccentricity * directrix) / (1 + (eccentricity * Math.Cos(alpha - thetaZero))); x = (float)((r * Math.Cos(alpha) * scaler) + graphCenterX + satX); y = (float)((r * Math.Sin(alpha) * scaler) + graphCenterY - satY); P2 = new PointF(x, y); //g.FillEllipse(burnBrush, x - 5, y - 5, 10, 10); } // DEBUG LINES if (debug) { PointF center = new PointF((float)(graphCenterX + satX), (float)(graphCenterY - satY)); x = (float)((200 * Math.Cos(thetaZero)) + center.X); y = (float)((200 * Math.Sin(thetaZero)) + center.Y); g.DrawLine(burnPen, center, new PointF(x, y)); g.DrawString("ThetaZero " + debugstr, font, textBrush, x, y); x = (float)((200 * Math.Cos(alphaZero)) + center.X); y = (float)((200 * Math.Sin(alphaZero)) + center.Y); g.DrawLine(burnPen, center, new PointF(x, y)); g.DrawString("AlphaZero " + debugstr, font, textBrush, x, y); x = (float)((200 * Math.Cos(REF)) + center.X); y = (float)((200 * Math.Sin(REF)) + center.Y); g.DrawLine(burnPen, center, new PointF(x, y)); g.DrawString("REF " + debugstr, font, textBrush, x, y); g.DrawArc(burnPen, center.X - 180, center.Y - 180, 360, 360, (float)Helper.rad2deg(REF), (float)Helper.rad2deg(alphaZero - REF)); g.DrawArc(burnPen, center.X - 160, center.Y - 160, 320, 320, (float)Helper.rad2deg(alphaZero), (float)Helper.rad2deg(thetaZero - alphaZero)); } }
private void drawPatchedConic(Graphics g, Orbit orbit, double thetaStart, double thetaEnd, Color orbitColor, bool relativeToParent) { int steps = 60; // Number of line segments double totTheta = thetaEnd - thetaStart; double thetaStep = totTheta / steps; double theta; PointF?lastPoint = null; PointF?point = null; PointF center; Pen localPen = new Pen(orbitColor, 2f); Brush localBrush = new SolidBrush(orbitColor); for (int i = 0; i <= steps; i++) { // IF relativeToParent, recalculate satX/Y and thetaZero each time. if (relativeToParent) { theta = Helper.deg2rad(180 - ((i * thetaStep) + thetaStart)) + thetaZeroNoREF; double time = orbit.UTAtTrueAnomaly(theta - thetaZeroNoREF); Tuple <double, double, double> pos = bodyOrbit.PositionAt(time, bodyNonRotFrame); satX = pos.Item1 * scaler; satY = pos.Item3 * scaler; if (pos.Item3 <= 0) { thetaZero = Math.Acos(pos.Item1 / Math.Sqrt(Math.Pow(pos.Item1, 2) + Math.Pow(pos.Item3, 2))) + thetaZeroNoREF; } else { thetaZero = (Helper.deg2rad(360) - Math.Acos(pos.Item1 / Math.Sqrt(Math.Pow(pos.Item1, 2) + Math.Pow(pos.Item3, 2)))) + thetaZeroNoREF; } } theta = Helper.deg2rad(180 - ((i * thetaStep) + thetaStart)) + thetaZero; Tuple <double, double> XY = getXYfromTheta(theta, orbit, relativeToParent); point = new PointF((float)XY.Item1, (float)XY.Item2); if (lastPoint != null) { g.DrawLine(localPen, (PointF)lastPoint, (PointF)point); g.DrawLine(orbitPen3, (PointF)lastPoint, (PointF)point); lastPoint = point; } else { lastPoint = point; } if (i % 10 == 0 && debug) { center = new PointF((float)(graphCenterX + satX), (float)(graphCenterY - satY)); g.DrawLine(orbitPen, (PointF)point, center); float x = (float)((300 * Math.Cos(thetaZero)) + center.X); float y = (float)((300 * Math.Sin(thetaZero)) + center.Y); g.DrawLine(burnPen, center, new PointF(x, y)); g.DrawString("ThetaZero ", font, textBrush, x, y); } if (i == 0 && eccentricity >= 1) { float size = 10; center = (PointF)point; PointF[] shape = new PointF[3]; shape[0] = new PointF(center.X + (size * -1f), center.Y + (size * -1.0f)); shape[1] = new PointF(center.X + (size * 1f), center.Y + (size * -1.0f)); shape[2] = new PointF(center.X + (size * 0f), center.Y + (size * 0f)); //g.FillPolygon(EnterSoiBrush, shape); g.FillEllipse(EnterSoiBrush, center.X - (size / 2), center.Y - (size / 2), size, size); } else if (i == steps && !double.IsNaN(orbit.TimeToSOIChange)) { float size = 10; center = (PointF)point; PointF[] shape = new PointF[3]; shape[0] = new PointF(center.X + (size * -1f), center.Y + (size * 1f)); shape[1] = new PointF(center.X + (size * 1f), center.Y + (size * 1f)); shape[2] = new PointF(center.X + (size * 0f), center.Y + (size * 0f)); //g.FillPolygon(ExitSoiBrush, shape); g.FillEllipse(ExitSoiBrush, center.X - (size / 2), center.Y - (size / 2), size, size); } } }
protected override void OnPaint(PaintEventArgs e) { Graphics g = e.Graphics; g.SmoothingMode = SmoothingMode.HighQuality; g.TextRenderingHint = TextRenderingHint.ClearTypeGridFit; // DEBUG TEST //g.FillRectangle(new SolidBrush(Color.Maroon), 0, 0, this.Width, this.Height); // Check for body and orbitset if (currentOrbit != null) { // Determine scaler int maxSizePx; if (this.Width < this.Height) { maxSizePx = this.Width; } else { maxSizePx = this.Height; } // Get biggest apopapsis of satellites double satMaxApo = 0; // Check of vessel orbit is biggest if (currentOrbit.Apoapsis > satMaxApo) { double maxDist = (currentOrbit.Apoapsis * 2.25) / zoom; // The .25 is to have some margin to the edges of the graph scaler = maxSizePx / maxDist; } else { scaler = maxSizePx / ((satMaxApo * 2.25) / zoom); } // Set Center of graph graphCenterX = (Width / 2); graphCenterY = (Height / 2); // Add manual offset graphCenterX += (float)(slideX + slideXtmp); graphCenterY += (float)(slideY + slideYtmp); // Draw Body float left = graphCenterX - (float)(currentOrbit.Body.EquatorialRadius * scaler); float top = graphCenterY - (float)(currentOrbit.Body.EquatorialRadius * scaler); float width = (float)(currentOrbit.Body.EquatorialRadius * 2 * scaler); float height = (float)(currentOrbit.Body.EquatorialRadius * 2 * scaler); RectangleF rect = new RectangleF(left, top, width, height); g.FillEllipse(bodyBrush, rect); // Draw satellites foreach (CelestialBody sat in bodySatellites) { Orbit orbit = sat.Orbit; MakeOrbitConstants(g, orbit); drawPatchedConic(g, orbit, 0, 360, orbitColor); drawCurrentPosition(g, orbit); } MakeOrbitConstants(g, currentOrbit, false, "CurrentOrbit"); drawPatchedConic(g, currentOrbit, 0, 360, orbitColor); drawPeriapse(g, currentOrbit); drawApoapse(g, currentOrbit); drawAscDescNodes(g, currentOrbit); drawCurrentPosition(g, currentOrbit); if (burnNodes != null) { int s = 0; for (int i = 0; i < burnNodes.Count; i++) { Node burnNode = burnNodes[i]; drawBurnPoint(g, burnNode); if (!double.IsNaN(burnNode.Orbit.TimeToSOIChange)) { double SOIUT = burnNode.Orbit.TimeToSOIChange + UT; double TAatSOI = burnNode.Orbit.TrueAnomalyAtUT(SOIUT); double burnTA = burnNode.Orbit.TrueAnomalyAtUT(burnNode.UT); // Swap thetaStart and thetaEnd is orbit is retrograde if (burnNode.Orbit.Inclination > Helper.deg2rad(90) && burnNode.Orbit.Inclination <= Helper.deg2rad(275)) { double tmp = burnTA; burnTA = TAatSOI; TAatSOI = tmp; } MakeOrbitConstants(g, burnNode.Orbit, false, "Node " + i.ToString()); drawPatchedConic(g, burnNode.Orbit, Helper.rad2deg(burnTA) + 180, Helper.rad2deg(TAatSOI) + 180, burnOrbitColor[i + s % 3]); Orbit SOIorbit = burnNode.Orbit.NextOrbit; while (SOIorbit != null) { s++; double entryTA = SOIorbit.TrueAnomalyAtUT(SOIUT); SOIUT = SOIorbit.TimeToSOIChange + UT; if (!double.IsNaN(SOIUT)) { TAatSOI = SOIorbit.TrueAnomalyAtUT(SOIUT); } else { TAatSOI = Helper.deg2rad(360); entryTA = 0; } // Swap thetaStart and thetaEnd is orbit is retrograde if (SOIorbit.Inclination > Helper.deg2rad(90) && SOIorbit.Inclination <= Helper.deg2rad(275)) { double tmp = entryTA; entryTA = TAatSOI; TAatSOI = tmp; } satX = 0; satY = 0; if (SOIorbit.Body.Name != body.Name && SOIorbit.Body.Name != "Sun") { // ORBIT AROUND ANTOHER BODY double CloseTime = SOIorbit.TimeToPeriapsis + burnNode.Orbit.TimeToSOIChange + UT; MakeOrbitConstants(g, SOIorbit.Body.Orbit, false, "SOI Orbit Blob"); drawBlob(g, SOIorbit.Body.Orbit, CloseTime); // This need to be done with satX/Y at 0, becouse it is relative to main body satX = SOIorbit.Body.Orbit.PositionAt(UT, bodyNonRotFrame).Item1 *scaler; satY = SOIorbit.Body.Orbit.PositionAt(UT, bodyNonRotFrame).Item3 *scaler; MakeOrbitConstants(g, SOIorbit, false, -1, "SOI Orbit local", true); drawPatchedConic(g, SOIorbit, Helper.rad2deg(entryTA) + 180, Helper.rad2deg(TAatSOI) + 180, burnOrbitColor[(i + s) % 3]); drawPeriapse(g, SOIorbit); // Main body relative orbit satX = SOIorbit.Body.Orbit.PositionAt(CloseTime, bodyNonRotFrame).Item1 *scaler; satY = SOIorbit.Body.Orbit.PositionAt(CloseTime, bodyNonRotFrame).Item3 *scaler; relPeriapse = -1; MakeOrbitConstants(g, SOIorbit, true, CloseTime, "SOI Orbit Relative", true); drawPatchedConic(g, SOIorbit, Helper.rad2deg(entryTA) + 180, Helper.rad2deg(TAatSOI) + 180, burnOrbitColor[(i + s) % 3], true); drawPeriapse(g, relPeriapseX, relPeriapseY); } else { MakeOrbitConstants(g, SOIorbit, false, "SOI Orbit " + s.ToString()); drawPatchedConic(g, SOIorbit, Helper.rad2deg(entryTA) + 180, Helper.rad2deg(TAatSOI) + 180, burnOrbitColor[(i + s) % 3]); drawPeriapse(g, SOIorbit); } if (SOIorbit.Eccentricity < 1 && double.IsNaN(SOIorbit.TimeToSOIChange)) { drawApoapse(g, SOIorbit); drawAscDescNodes(g, SOIorbit); } SOIorbit = SOIorbit.NextOrbit; } } else { satX = 0; satY = 0; MakeOrbitConstants(g, burnNode.Orbit, false, "Burn Orbit"); drawPatchedConic(g, burnNode.Orbit, 0, 360, burnOrbitColor[(i + s) % 3]); drawPeriapse(g, burnNode.Orbit); drawApoapse(g, burnNode.Orbit); drawAscDescNodes(g, burnNode.Orbit); } } } } }
public void updateChartData(object sender, EventArgs e) { if (connected && krpc.CurrentGameScene == KRPC.Client.Services.KRPC.GameScene.Flight && graphStreams != null) { double altitude = graphStreams.GetData(DataType.flight_meanAltitude); double apoapsis = graphStreams.GetData(DataType.orbit_apoapsisAltitude); double periapsis = graphStreams.GetData(DataType.orbit_periapsisAltitude); double speed = graphStreams.GetData(DataType.orbit_speed); double MET = graphStreams.GetData(DataType.vessel_MET); double elevation = graphStreams.GetData(DataType.flight_elevation); float gee = graphStreams.GetData(DataType.flight_gForce); float dynPress = graphStreams.GetData(DataType.flight_dynamicPressure); float roll = graphStreams.GetData(DataType.flight_inertial_roll); float pitch = graphStreams.GetData(DataType.flight_inertial_pitch); Tuple <double, double, double> prograde = graphStreams.GetData(DataType.flight_prograde); float aoa = graphStreams.GetData(DataType.flight_angleOfAttack); float yaw = graphStreams.GetData(DataType.flight_inertial_yaw); double tapo = graphStreams.GetData(DataType.orbit_timeToApoapsis); double lat = graphStreams.GetData(DataType.flight_map_latitude); double lon = graphStreams.GetData(DataType.flight_map_longitude); // Limit taop to 120 minutes if (tapo > 120 * 60) { tapo = 120 * 60; } // Calculate Range double RANGE = 0; if (originLat != null) { float R = graphStreams.GetData(DataType.body_radius); // body radius in metres double lat1 = (double)originLat; double lon1 = originLon; double rad1 = Helper.deg2rad(lat); double rad2 = Helper.deg2rad(lat1); double deltaRad = Helper.deg2rad((lat1 - lat)); double deltaLambda = Helper.deg2rad((lon1 - lon)); double a = Math.Sin(deltaRad / 2) * Math.Sin(deltaRad / 2) + Math.Cos(rad1) * Math.Cos(rad2) * Math.Sin(deltaLambda / 2) * Math.Sin(deltaLambda / 2); double c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a)); RANGE = R * c; } addValueToChart(chartData["lat"], MET, lat, 10000); addValueToChart(chartData["lon"], MET, lon, 10000); // HDOT if (prevAlt.Key != 0) { double HDOT = (double)((altitude - prevAlt.Value) / (MET - prevAlt.Key)); addValueToChart(chartData["hdot"], MET, HDOT, 3000); addValueToChart(chartData["hhdot"], HDOT, altitude, 3000); } prevAlt = new KeyValuePair <double, double?>(MET, altitude); // FLIGHT PATH ANGLE // Flight path angle is the angle between the velocity vector (prograde), and the local horizon. // Surface direction unit length double surf = Math.Sqrt(Math.Pow(prograde.Item2, 2) + Math.Pow(prograde.Item3, 2)); // Flight path angle double fpa; if (surf < 0.00001) { fpa = 90; } else { fpa = Helper.rad2deg(Math.Atan(prograde.Item1 / surf)); } addValueToChart(chartData["FlightangleVelocity"], speed, fpa, 3000); addValueToChart(chartData["geeVel"], speed, gee, 3000); addValueToChart(chartData["altitudeTime"], MET, altitude); addValueToChart(chartData["apoapsisTime"], MET, apoapsis); addValueToChart(chartData["periapsisTime"], (int)MET, periapsis); addValueToChart(chartData["geeTime"], (int)MET, gee); addValueToChart(chartData["terrainTime"], (int)MET, elevation); addValueToChart(chartData["dynPresTime"], (int)MET, dynPress); addValueToChart(chartData["rollTime"], (int)MET, roll); addValueToChart(chartData["pitchTime"], (int)MET, pitch); addValueToChart(chartData["yawTime"], (int)MET, yaw); addValueToChart(chartData["altitudeSpeed"], (int)speed, altitude, 3000); addValueToChart(chartData["timeToApoSpeed"], (int)speed, tapo, 3000); addValueToChart(chartData["altitudeRange"], (int)RANGE, altitude, 3000); } }