From: Pat Thoyts Date: Sat, 9 Aug 2014 13:08:14 +0000 (+0100) Subject: Provided WinForms user interface. X-Git-Url: http://privyetmir.co.uk/gitweb?a=commitdiff_plain;ds=inline;p=MervsSolver Provided WinForms user interface. Converted the console mode version into a standard WinForms UI with a custom plotting usercontrol. Support for working in Visual Studio. Signed-off-by: Pat Thoyts --- diff --git a/.gitignore b/.gitignore index 50b22b1..9229094 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,9 @@ /SolverTest/bin /SolverTest/obj /SolverTest/test-results/ +/packages/ *.userprefs *.prg +*.suo *~ diff --git a/MervsSolver/MainForm.Designer.cs b/MervsSolver/MainForm.Designer.cs new file mode 100644 index 0000000..b88f8ab --- /dev/null +++ b/MervsSolver/MainForm.Designer.cs @@ -0,0 +1,275 @@ +namespace MervsSolver +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.panel1 = new System.Windows.Forms.Panel(); + this.label5 = new System.Windows.Forms.Label(); + this.stepsCtrl = new System.Windows.Forms.NumericUpDown(); + this.label4 = new System.Windows.Forms.Label(); + this.muCtrl = new System.Windows.Forms.NumericUpDown(); + this.label3 = new System.Windows.Forms.Label(); + this.dvCtrl = new System.Windows.Forms.NumericUpDown(); + this.label2 = new System.Windows.Forms.Label(); + this.label1 = new System.Windows.Forms.Label(); + this.dxCtrl = new System.Windows.Forms.NumericUpDown(); + this.plotter1 = new MervsSolver.Plotter(); + this.label6 = new System.Windows.Forms.Label(); + this.limitCtrl = new System.Windows.Forms.NumericUpDown(); + this.panel1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.stepsCtrl)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.muCtrl)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.dvCtrl)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.dxCtrl)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.limitCtrl)).BeginInit(); + this.SuspendLayout(); + // + // panel1 + // + this.panel1.Controls.Add(this.limitCtrl); + this.panel1.Controls.Add(this.label6); + this.panel1.Controls.Add(this.label5); + this.panel1.Controls.Add(this.stepsCtrl); + this.panel1.Controls.Add(this.label4); + this.panel1.Controls.Add(this.muCtrl); + this.panel1.Controls.Add(this.label3); + this.panel1.Controls.Add(this.dvCtrl); + this.panel1.Controls.Add(this.label2); + this.panel1.Controls.Add(this.label1); + this.panel1.Controls.Add(this.dxCtrl); + this.panel1.Dock = System.Windows.Forms.DockStyle.Top; + this.panel1.Location = new System.Drawing.Point(0, 0); + this.panel1.Name = "panel1"; + this.panel1.Size = new System.Drawing.Size(598, 54); + this.panel1.TabIndex = 0; + // + // label5 + // + this.label5.AutoSize = true; + this.label5.Location = new System.Drawing.Point(3, 26); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(35, 13); + this.label5.TabIndex = 9; + this.label5.Text = "label5"; + // + // stepsCtrl + // + this.stepsCtrl.DecimalPlaces = 2; + this.stepsCtrl.Increment = new decimal(new int[] { + 1, + 0, + 0, + 131072}); + this.stepsCtrl.Location = new System.Drawing.Point(347, 3); + this.stepsCtrl.Maximum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.stepsCtrl.Name = "stepsCtrl"; + this.stepsCtrl.Size = new System.Drawing.Size(50, 20); + this.stepsCtrl.TabIndex = 8; + this.stepsCtrl.Value = new decimal(new int[] { + 8, + 0, + 0, + 131072}); + this.stepsCtrl.ValueChanged += new System.EventHandler(this.Numeric_ValueChanged); + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(291, 5); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(50, 13); + this.label4.TabIndex = 7; + this.label4.Text = "Step size"; + // + // muCtrl + // + this.muCtrl.DecimalPlaces = 1; + this.muCtrl.Increment = new decimal(new int[] { + 1, + 0, + 0, + 65536}); + this.muCtrl.Location = new System.Drawing.Point(235, 3); + this.muCtrl.Name = "muCtrl"; + this.muCtrl.Size = new System.Drawing.Size(50, 20); + this.muCtrl.TabIndex = 5; + this.muCtrl.Value = new decimal(new int[] { + 1, + 0, + 0, + 65536}); + this.muCtrl.ValueChanged += new System.EventHandler(this.Numeric_ValueChanged); + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(208, 5); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(21, 13); + this.label3.TabIndex = 4; + this.label3.Text = "mu"; + // + // dvCtrl + // + this.dvCtrl.DecimalPlaces = 1; + this.dvCtrl.Increment = new decimal(new int[] { + 1, + 0, + 0, + 65536}); + this.dvCtrl.Location = new System.Drawing.Point(133, 3); + this.dvCtrl.Name = "dvCtrl"; + this.dvCtrl.Size = new System.Drawing.Size(48, 20); + this.dvCtrl.TabIndex = 3; + this.dvCtrl.Value = new decimal(new int[] { + 1, + 0, + 0, + 65536}); + this.dvCtrl.ValueChanged += new System.EventHandler(this.Numeric_ValueChanged); + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(113, 5); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(14, 13); + this.label2.TabIndex = 2; + this.label2.Text = "V"; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(3, 5); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(14, 13); + this.label1.TabIndex = 1; + this.label1.Text = "X"; + // + // dxCtrl + // + this.dxCtrl.DecimalPlaces = 1; + this.dxCtrl.Increment = new decimal(new int[] { + 1, + 0, + 0, + 65536}); + this.dxCtrl.Location = new System.Drawing.Point(23, 3); + this.dxCtrl.Name = "dxCtrl"; + this.dxCtrl.Size = new System.Drawing.Size(63, 20); + this.dxCtrl.TabIndex = 0; + this.dxCtrl.Value = new decimal(new int[] { + 1, + 0, + 0, + 65536}); + this.dxCtrl.ValueChanged += new System.EventHandler(this.Numeric_ValueChanged); + // + // plotter1 + // + this.plotter1.BackColor = System.Drawing.Color.White; + this.plotter1.Coords = null; + this.plotter1.Dock = System.Windows.Forms.DockStyle.Fill; + this.plotter1.Location = new System.Drawing.Point(0, 54); + this.plotter1.Name = "plotter1"; + this.plotter1.Size = new System.Drawing.Size(598, 416); + this.plotter1.TabIndex = 1; + // + // label6 + // + this.label6.AutoSize = true; + this.label6.Location = new System.Drawing.Point(403, 5); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(28, 13); + this.label6.TabIndex = 10; + this.label6.Text = "Limit"; + // + // limitCtrl + // + this.limitCtrl.Increment = new decimal(new int[] { + 100, + 0, + 0, + 0}); + this.limitCtrl.Location = new System.Drawing.Point(437, 3); + this.limitCtrl.Maximum = new decimal(new int[] { + 10000, + 0, + 0, + 0}); + this.limitCtrl.Name = "limitCtrl"; + this.limitCtrl.Size = new System.Drawing.Size(57, 20); + this.limitCtrl.TabIndex = 11; + this.limitCtrl.Value = new decimal(new int[] { + 2000, + 0, + 0, + 0}); + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(598, 470); + this.Controls.Add(this.plotter1); + this.Controls.Add(this.panel1); + this.Name = "MainForm"; + this.Text = "MainForm"; + this.Load += new System.EventHandler(this.MainForm_Load); + this.panel1.ResumeLayout(false); + this.panel1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.stepsCtrl)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.muCtrl)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.dvCtrl)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.dxCtrl)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.limitCtrl)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.Panel panel1; + private System.Windows.Forms.NumericUpDown muCtrl; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.NumericUpDown dvCtrl; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.NumericUpDown dxCtrl; + private System.Windows.Forms.NumericUpDown stepsCtrl; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.Label label5; + private Plotter plotter1; + private System.Windows.Forms.NumericUpDown limitCtrl; + private System.Windows.Forms.Label label6; + } +} \ No newline at end of file diff --git a/MervsSolver/MainForm.cs b/MervsSolver/MainForm.cs new file mode 100644 index 0000000..63db744 --- /dev/null +++ b/MervsSolver/MainForm.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Diagnostics; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Windows.Forms; +using MervsSolver; + +namespace MervsSolver +{ + public partial class MainForm : Form + { + public MainForm() + { + InitializeComponent(); + label5.Text = ""; + } + + private void Solve() + { + double x0 = (double)dxCtrl.Value; + double v0 = (double)dvCtrl.Value; + double mu = (double)muCtrl.Value; + double steps = (double)stepsCtrl.Value; + int limit = (int)limitCtrl.Value; + Stopwatch t = new Stopwatch(); + t.Start(); + Solver solver = new Solver(x0, v0, mu, steps, limit); + t.Stop(); + label5.Text = String.Format("{0} values obtained in {1}ms.", solver.Result.Count, t.ElapsedMilliseconds); + plotter1.Coords = solver.Result; + } + + private void button1_Click(object sender, EventArgs e) + { + Solve(); + } + private void Numeric_ValueChanged(object sender, EventArgs e) + { + Solve(); + } + private void MainForm_Load(object sender, EventArgs e) + { + Solve(); + } + + } +} diff --git a/MervsSolver/MainForm.resx b/MervsSolver/MainForm.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/MervsSolver/MainForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/MervsSolver/MervsSolver.csproj b/MervsSolver/MervsSolver.csproj index 0ff94ec..6db1f30 100644 --- a/MervsSolver/MervsSolver.csproj +++ b/MervsSolver/MervsSolver.csproj @@ -1,4 +1,4 @@ - + Debug @@ -6,7 +6,7 @@ 10.0.0 2.0 {BFBAA38C-7F6F-44BB-A4DA-C943818FDD3A} - Exe + WinExe MervsSolver MervsSolver @@ -19,7 +19,7 @@ prompt 4 true - x86 + AnyCPU .1 .1 .1 .1 @@ -29,16 +29,43 @@ prompt 4 true - x86 + AnyCPU + + + + + + + + + Form + + + MainForm.cs + + + UserControl + + + Plotter.cs + + + + MainForm.cs + + + Plotter.cs + + \ No newline at end of file diff --git a/MervsSolver/Plotter.Designer.cs b/MervsSolver/Plotter.Designer.cs new file mode 100644 index 0000000..39213f4 --- /dev/null +++ b/MervsSolver/Plotter.Designer.cs @@ -0,0 +1,47 @@ +namespace MervsSolver +{ + partial class Plotter + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.SuspendLayout(); + // + // Plotter + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.BackColor = System.Drawing.Color.White; + this.Name = "Plotter"; + this.Size = new System.Drawing.Size(217, 211); + this.Resize += new System.EventHandler(this.Plotter_Resize); + this.ResumeLayout(false); + + } + + #endregion + } +} diff --git a/MervsSolver/Plotter.cs b/MervsSolver/Plotter.cs new file mode 100644 index 0000000..4285cb0 --- /dev/null +++ b/MervsSolver/Plotter.cs @@ -0,0 +1,107 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.Drawing.Drawing2D; +using System.Data; +using System.Linq; +using System.Text; +using System.Windows.Forms; + +namespace MervsSolver +{ + public partial class Plotter : UserControl + { + public Plotter() + { + InitializeComponent(); + } + + private List mCoords = null; + public List Coords + { + get { return mCoords; } + set + { + mCoords = value; + Invalidate(); + } + } + + protected override void OnPaint(PaintEventArgs peArgs) + { + Graphics g = peArgs.Graphics; + g.SmoothingMode = SmoothingMode.AntiAlias; + using (SolidBrush backBrush = new SolidBrush(this.BackColor)) + using (SolidBrush plotBrush = new SolidBrush(Color.Red)) + using (SolidBrush foreBrush = new SolidBrush(this.ForeColor)) + using (Pen axisPen = new Pen(foreBrush, 1.2f)) + using (Pen linePen = new Pen(plotBrush, 1.2f)) + { + // Erase client area + g.FillRectangle(backBrush, this.ClientRectangle); + + // draw axes + int center_x = ClientRectangle.Width / 2; + int center_y = ClientRectangle.Height / 2; + g.DrawLine(axisPen, ClientRectangle.Left, center_y, ClientRectangle.Right, center_y); + g.DrawLine(axisPen, center_x, ClientRectangle.Top, center_x, ClientRectangle.Bottom); + + if (Coords != null) + { + double max_x = Coords.Max(v => v.X); + double max_y = Coords.Max(v => v.Y); + double min_x = Coords.Min(v => v.X); + double min_y = Coords.Min(v => v.Y); + + double dx = Math.Abs(max_x - min_x); + double dy = Math.Abs(max_y - min_y); + + // draw max x val + DrawXLabel(g, String.Format("{0:0.00}", min_x), foreBrush, true); + DrawXLabel(g, String.Format("{0:0.00}", max_x), foreBrush, false); + DrawYLabel(g, String.Format("{0:0.00}", max_y), foreBrush, true); + DrawYLabel(g, String.Format("{0:0.00}", min_y), foreBrush, false); + + List points = new List(); + foreach (Coord c in Coords) + { + int x = (int)((c.X / dx) * ClientRectangle.Width + ClientRectangle.Left + (ClientRectangle.Width/2)); + int y = (int)((c.Y / dy) * ClientRectangle.Height + ClientRectangle.Top + (ClientRectangle.Height/2)); + points.Add(new Point(x, y)); + } + g.DrawLines(linePen, points.ToArray()); + } + } + } + + private void DrawXLabel(Graphics g, string label, Brush brush, bool isLeft) + { + int center_y = ClientRectangle.Height / 2; + Size size = TextRenderer.MeasureText(label, Font); + Point pt; + if (isLeft) + pt = new Point(ClientRectangle.Left, center_y + size.Height); + else + pt = new Point(ClientRectangle.Right - size.Width, center_y + size.Height); + g.DrawString(label, this.Font, brush, pt, StringFormat.GenericTypographic); + } + + private void DrawYLabel(Graphics g, string label, Brush brush, bool isTop) + { + int center_x = ClientRectangle.Width / 2; + Size size = TextRenderer.MeasureText(label, Font); + Point pt; + if (isTop) + pt = new Point(center_x - size.Width, ClientRectangle.Top + size.Height); + else + pt = new Point(center_x - size.Width, ClientRectangle.Bottom - size.Height); + g.DrawString(label, this.Font, brush, pt, StringFormat.GenericTypographic); + } + + private void Plotter_Resize(object sender, EventArgs e) + { + Invalidate(); + } + } +} diff --git a/MervsSolver/Plotter.resx b/MervsSolver/Plotter.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/MervsSolver/Plotter.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/MervsSolver/Program.cs b/MervsSolver/Program.cs index d7ba69f..e6a06e3 100644 --- a/MervsSolver/Program.cs +++ b/MervsSolver/Program.cs @@ -2,12 +2,22 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; +using System.Threading.Tasks; +using System.Windows.Forms; namespace MervsSolver { class MainClass { - public static void Main(string[] args) + [STAThread] + static void Main() + { + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new MainForm()); + } + + public static void MonoMain(string[] args) { double x0, v0, mu, steps; if (Double.TryParse(args[0], out x0) @@ -15,7 +25,7 @@ namespace MervsSolver && Double.TryParse(args[2], out mu) && Double.TryParse(args[3], out steps)) { - Solver solver = new Solver(x0, v0, mu, steps); + Solver solver = new Solver(x0, v0, mu, steps, 2000); Process gnuplot = Gnuplot(mu); foreach (Coord coord in solver.Result) { diff --git a/MervsSolver/Solver.cs b/MervsSolver/Solver.cs index 73a70cc..c3fcf56 100644 --- a/MervsSolver/Solver.cs +++ b/MervsSolver/Solver.cs @@ -6,10 +6,10 @@ namespace MervsSolver { public class Solver { - List mResult = new List(); + private List mResult = new List(); public List Result { get { return mResult; } } - public Solver(double initialDisplacement, double initialVelocity, double continuousParameter, double stepSize) + public Solver(double initialDisplacement, double initialVelocity, double continuousParameter, double stepSize, int limit) { double x0 = initialDisplacement; double v0 = initialVelocity; @@ -55,14 +55,17 @@ namespace MervsSolver if (i == 50) { for (int n = 1; n != i; ++n) + { mResult.Add(new Coord(0 + (A[n] * -75), (E[n] * -75))); + if (mResult.Count > limit) return; + } i = 0; } v0 = v1; x0 = x1; if (v0 == 0) { - if (i == 0 || mResult.Count > 1000) + if (i == 0 || mResult.Count > limit) break; if (E[i - 1] < 0) z = d; diff --git a/SolverTest/SolverTest.csproj b/SolverTest/SolverTest.csproj index dddebaa..f4b3fec 100644 --- a/SolverTest/SolverTest.csproj +++ b/SolverTest/SolverTest.csproj @@ -1,4 +1,4 @@ - + Debug @@ -6,6 +6,7 @@ 10.0.0 2.0 {459AC64B-AA17-492D-80E4-A4A91AF14296} + {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} Library SolverTest SolverTest @@ -29,10 +30,23 @@ false - - + + ..\packages\NUnitTestAdapter.1.1\lib\nunit.core.dll + False + + + ..\packages\NUnitTestAdapter.1.1\lib\nunit.core.interfaces.dll False + + False + ..\packages\NUnit.2.6.3\lib\nunit.framework.dll + + + ..\packages\NUnitTestAdapter.1.1\lib\nunit.util.dll + False + + @@ -42,6 +56,7 @@ + PreserveNewest diff --git a/SolverTest/Test.cs b/SolverTest/Test.cs index 7517495..4771c0c 100644 --- a/SolverTest/Test.cs +++ b/SolverTest/Test.cs @@ -7,13 +7,13 @@ using MervsSolver; namespace SolverTest { - [TestFixture()] + [TestFixture] public class Test { - [Test()] + [Test] public void solver_regression_test() { - Solver solver = new Solver(0.1, 0.1, 0.1, 0.1); + Solver solver = new Solver(0.1, 0.1, 0.1, 0.1, 2000); string[] lines = File.ReadAllLines("test.data"); Assert.That(solver.Result.Count == lines.Length, "generated less results than expected ({0} should be {1})", solver.Result.Count, lines.Length); diff --git a/SolverTest/packages.config b/SolverTest/packages.config new file mode 100644 index 0000000..c4be002 --- /dev/null +++ b/SolverTest/packages.config @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file