using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Drawing.Drawing2D; using RungeKutta.Integrators; namespace RungeKutta { public partial class Main : Form { Key key = null; Manager manager; State initialState = new State(); float timeStep = .1f; float timeToRun = 5.0f; float minT, maxT, minY, maxY; List IntegrationPens = new List(); List IntegrationToggles = new List(); public Main() { InitializeComponent(); manager = new Manager(); float penWidth = 4; IntegrationPens.Add(new Pen(Color.Red, penWidth)); IntegrationPens.Add(new Pen(Color.Blue, penWidth)); IntegrationPens.Add(new Pen(Color.Yellow, penWidth)); IntegrationPens.Add(new Pen(Color.Orange, penWidth)); IntegrationPens.Add(new Pen(Color.Green, penWidth)); IntegrationPens.Add(new Pen(Color.Cyan, penWidth)); IntegrationPens.Add(new Pen(Color.Purple, penWidth)); IntegrationPens.Add(new Pen(Color.Brown, penWidth)); IntegrationPens.Add(new Pen(Color.CadetBlue, penWidth)); IntegrationPens.Add(new Pen(Color.Black, penWidth)); IntegrationPens.Add(new Pen(Color.White, penWidth)); if(IntegrationPens.Count < manager.Integrators.Count) throw new Exception("Too many integrators for not enough pens."); for (int x = 0; x < manager.Integrators.Count; ++x) IntegrationToggles.Add(false); //initialState.prevPos = initialState.prevVel = initialState.prevAccel = float.PositiveInfinity; UpdateManager(); manager.Compute(timeStep, timeToRun, initialState); foreach (Control control in KeyPanel.Controls) { int index = control.Name[control.Name.Length - 1] - '1'; if (control is CheckBox) { CheckBox check = control as CheckBox; if (manager.Integrators.Count > index) { check.Text = manager.Integrators[index].ToString(); check.Checked = IntegrationToggles[index]; check.CheckedChanged += delegate(Object sender, EventArgs e) { IntegrationToggles[index] = check.Checked; Refresh(); }; } else { check.Visible = false; } } else if (control is PictureBox) { PictureBox box = control as PictureBox; if (manager.Integrators.Count > index) (control as PictureBox).BackColor = IntegrationPens[index].Color; } } } private void KeyButton_Click(object sender, EventArgs e) { if(!key.Visible) key.ShowDialog(this); Refresh(); } private float ConvertToUnitFactor(float original, float min, float max) { if (min > max) { float temp = min; min = max; max = temp; } return (original - min) / (max - min); } private PointF FromUnitFactorToPixel(PointF point) { return new PointF(point.X * PlotGraph.ClientSize.Width, (1.0f - point.Y) * PlotGraph.ClientSize.Height); } private PointF ConvertGraphToPixel(PointF original) { return FromUnitFactorToPixel(new PointF( ConvertToUnitFactor(original.X, minT, maxT), ConvertToUnitFactor(original.Y, minY, maxY))); } private void PlotGraph_Paint(object sender, PaintEventArgs e) { //Draw axis: Pen axisPen = new Pen(Color.Black, 3); e.Graphics.DrawLine(axisPen, ConvertGraphToPixel(new PointF(0, minY - 1)), ConvertGraphToPixel(new PointF(0, maxY + 1))); e.Graphics.DrawLine(axisPen, ConvertGraphToPixel(new PointF(minT - 1, 0)), ConvertGraphToPixel(new PointF(maxT + 1, 0))); PointF[] Points = new PointF[(int)Math.Ceiling(timeToRun / timeStep * 1.1f)]; for (int x = 0; x < manager.Integrators.Count; ++x) { if (!IntegrationToggles[x]) continue; int Last = manager.ComputedValues[x].Count - 1; for (int t = 0; t <= Last; ++t) { Points[t] = ConvertGraphToPixel(new PointF( timeStep * (float)t * manager.Integrators[x].ForceEvaluations, manager.ComputedValues[x][t])); if (t > 0) { try { e.Graphics.DrawLine(IntegrationPens[x], Points[t - 1], Points[t]); } catch (Exception) { break; } } } } } private void Contants_KeyDown(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.Enter) { UpdateManager(); } } private void Constants_Leave(object sender, EventArgs e) { UpdateManager(); } private void UpdateField(ref TextBox text, ref float val) { float temp = val; if (float.TryParse(text.Text, out temp)) val = temp; text.Text = val.ToString(); } private float UpdateField(ref TextBox text, float val) { float temp = val; if (float.TryParse(text.Text, out temp)) val = temp; text.Text = val.ToString(); return val; } private void UpdateManager() { manager.ODE.A = UpdateField(ref ConstantForceText, manager.ODE.A); manager.ODE.B = UpdateField(ref DragFactorText, manager.ODE.B); manager.ODE.C = UpdateField(ref SpringConstantText, manager.ODE.C); UpdateField(ref InitialPositionText, ref initialState.position); UpdateField(ref InitialVelocityText, ref initialState.velocity); UpdateField(ref StepSizeText, ref timeStep); UpdateField(ref IntervalText, ref timeToRun); UpdateField(ref MinTText, ref minT); UpdateField(ref MinYText, ref minY); UpdateField(ref MaxTText, ref maxT); UpdateField(ref MaxYText, ref maxY); manager.Compute(timeStep, timeToRun, initialState); Refresh(); } private void PlotButton_Click(object sender, EventArgs e) { manager.Compute(timeStep, timeToRun, initialState); Refresh(); } private void Main_SizeChanged(object sender, EventArgs e) { Refresh(); } } }