Added a new project. Finished a while back.
This commit is contained in:
parent
4147a29fdc
commit
93f4ba647f
22
AirTrajectoryBuilder/AirTrajectoryBuilder.sln
Normal file
22
AirTrajectoryBuilder/AirTrajectoryBuilder.sln
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio Version 17
|
||||||
|
VisualStudioVersion = 17.12.35506.116 d17.12
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AirTrajectoryBuilder", "AirTrajectoryBuilder\AirTrajectoryBuilder.csproj", "{0EA33509-A4B2-4FB3-84E5-C9773FEDF0A9}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{0EA33509-A4B2-4FB3-84E5-C9773FEDF0A9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{0EA33509-A4B2-4FB3-84E5-C9773FEDF0A9}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{0EA33509-A4B2-4FB3-84E5-C9773FEDF0A9}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{0EA33509-A4B2-4FB3-84E5-C9773FEDF0A9}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
||||||
BIN
AirTrajectoryBuilder/AirTrajectoryBuilder.zip
Normal file
BIN
AirTrajectoryBuilder/AirTrajectoryBuilder.zip
Normal file
Binary file not shown.
@ -0,0 +1,15 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>WinExe</OutputType>
|
||||||
|
<TargetFramework>net9.0-windows</TargetFramework>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<UseWindowsForms>true</UseWindowsForms>
|
||||||
|
<ImplicitUsings>disable</ImplicitUsings>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Nerd_STF" Version="3.0.0-beta1" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@ -0,0 +1,17 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Update="Forms\MainForm.cs">
|
||||||
|
<SubType>Form</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Update="Forms\SweepCancelForm.cs">
|
||||||
|
<SubType>Form</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Update="Forms\SweepInfoViewer.cs">
|
||||||
|
<SubType>Form</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Update="Forms\SweepParametersForm.cs">
|
||||||
|
<SubType>Form</SubType>
|
||||||
|
</Compile>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
||||||
127
AirTrajectoryBuilder/AirTrajectoryBuilder/Forms/MainForm.Designer.cs
generated
Normal file
127
AirTrajectoryBuilder/AirTrajectoryBuilder/Forms/MainForm.Designer.cs
generated
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
using System.Drawing;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace AirTrajectoryBuilder
|
||||||
|
{
|
||||||
|
partial class MainForm
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Required designer variable.
|
||||||
|
/// </summary>
|
||||||
|
private System.ComponentModel.IContainer components = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clean up any resources being used.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing && (components != null))
|
||||||
|
{
|
||||||
|
components.Dispose();
|
||||||
|
}
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Windows Form Designer generated code
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Required method for Designer support - do not modify
|
||||||
|
/// the contents of this method with the code editor.
|
||||||
|
/// </summary>
|
||||||
|
private void InitializeComponent()
|
||||||
|
{
|
||||||
|
Menu = new MenuStrip();
|
||||||
|
MenuFile = new ToolStripMenuItem();
|
||||||
|
MenuFileNew = new ToolStripMenuItem();
|
||||||
|
MenuFileOpen = new ToolStripMenuItem();
|
||||||
|
MenuRun = new ToolStripMenuItem();
|
||||||
|
MenuRunSweep = new ToolStripMenuItem();
|
||||||
|
FileOpener = new OpenFileDialog();
|
||||||
|
MenuRunCancel = new ToolStripMenuItem();
|
||||||
|
Menu.SuspendLayout();
|
||||||
|
SuspendLayout();
|
||||||
|
//
|
||||||
|
// Menu
|
||||||
|
//
|
||||||
|
Menu.ImageScalingSize = new Size(32, 32);
|
||||||
|
Menu.Items.AddRange(new ToolStripItem[] { MenuFile, MenuRun });
|
||||||
|
Menu.Location = new Point(0, 0);
|
||||||
|
Menu.Name = "Menu";
|
||||||
|
Menu.Size = new Size(1263, 42);
|
||||||
|
Menu.TabIndex = 0;
|
||||||
|
Menu.Text = "menuStrip1";
|
||||||
|
//
|
||||||
|
// MenuFile
|
||||||
|
//
|
||||||
|
MenuFile.DropDownItems.AddRange(new ToolStripItem[] { MenuFileNew, MenuFileOpen });
|
||||||
|
MenuFile.Name = "MenuFile";
|
||||||
|
MenuFile.Size = new Size(71, 38);
|
||||||
|
MenuFile.Text = "File";
|
||||||
|
//
|
||||||
|
// MenuFileNew
|
||||||
|
//
|
||||||
|
MenuFileNew.Name = "MenuFileNew";
|
||||||
|
MenuFileNew.Size = new Size(221, 44);
|
||||||
|
MenuFileNew.Text = "New";
|
||||||
|
MenuFileNew.Click += MenuFileNew_Click;
|
||||||
|
//
|
||||||
|
// MenuFileOpen
|
||||||
|
//
|
||||||
|
MenuFileOpen.Name = "MenuFileOpen";
|
||||||
|
MenuFileOpen.Size = new Size(221, 44);
|
||||||
|
MenuFileOpen.Text = "Open...";
|
||||||
|
MenuFileOpen.Click += MenuFileOpen_Click;
|
||||||
|
//
|
||||||
|
// MenuRun
|
||||||
|
//
|
||||||
|
MenuRun.DropDownItems.AddRange(new ToolStripItem[] { MenuRunSweep, MenuRunCancel });
|
||||||
|
MenuRun.Name = "MenuRun";
|
||||||
|
MenuRun.Size = new Size(76, 38);
|
||||||
|
MenuRun.Text = "Run";
|
||||||
|
//
|
||||||
|
// MenuRunSweep
|
||||||
|
//
|
||||||
|
MenuRunSweep.Name = "MenuRunSweep";
|
||||||
|
MenuRunSweep.Size = new Size(359, 44);
|
||||||
|
MenuRunSweep.Text = "Sweep...";
|
||||||
|
MenuRunSweep.Click += MenuRunSweep_Click;
|
||||||
|
//
|
||||||
|
// FileOpener
|
||||||
|
//
|
||||||
|
FileOpener.Filter = "Scene files|*.sce|All files|*.*";
|
||||||
|
//
|
||||||
|
// MenuRunCancel
|
||||||
|
//
|
||||||
|
MenuRunCancel.Name = "MenuRunCancel";
|
||||||
|
MenuRunCancel.Size = new Size(359, 44);
|
||||||
|
MenuRunCancel.Text = "Cancel";
|
||||||
|
MenuRunCancel.Click += MenuRunCancel_Click;
|
||||||
|
//
|
||||||
|
// MainForm
|
||||||
|
//
|
||||||
|
AutoScaleDimensions = new SizeF(13F, 32F);
|
||||||
|
AutoScaleMode = AutoScaleMode.Font;
|
||||||
|
ClientSize = new Size(1263, 719);
|
||||||
|
Controls.Add(Menu);
|
||||||
|
MainMenuStrip = Menu;
|
||||||
|
Name = "MainForm";
|
||||||
|
Text = "MainForm";
|
||||||
|
Menu.ResumeLayout(false);
|
||||||
|
Menu.PerformLayout();
|
||||||
|
ResumeLayout(false);
|
||||||
|
PerformLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private MenuStrip Menu;
|
||||||
|
private ToolStripMenuItem MenuFile;
|
||||||
|
private ToolStripMenuItem MenuFileOpen;
|
||||||
|
private ToolStripMenuItem MenuFileNew;
|
||||||
|
private OpenFileDialog FileOpener;
|
||||||
|
private ToolStripMenuItem MenuRun;
|
||||||
|
private ToolStripMenuItem MenuRunSweep;
|
||||||
|
private ToolStripMenuItem MenuRunCancel;
|
||||||
|
}
|
||||||
|
}
|
||||||
447
AirTrajectoryBuilder/AirTrajectoryBuilder/Forms/MainForm.cs
Normal file
447
AirTrajectoryBuilder/AirTrajectoryBuilder/Forms/MainForm.cs
Normal file
@ -0,0 +1,447 @@
|
|||||||
|
using AirTrajectoryBuilder.ObjectModels;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Drawing;
|
||||||
|
using System;
|
||||||
|
using Nerd_STF.Mathematics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Drawing.Drawing2D;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Threading;
|
||||||
|
using AirTrajectoryBuilder.Forms;
|
||||||
|
|
||||||
|
namespace AirTrajectoryBuilder;
|
||||||
|
|
||||||
|
public partial class MainForm : Form
|
||||||
|
{
|
||||||
|
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||||||
|
public Scene Scene { get; set; }
|
||||||
|
|
||||||
|
private readonly float scalingFactor;
|
||||||
|
private readonly string baseFolder, sceneFolder;
|
||||||
|
|
||||||
|
public SweepParameters? SweepParameters;
|
||||||
|
|
||||||
|
private CancellationTokenSource? simCancel;
|
||||||
|
private SimulationResult? simResult;
|
||||||
|
private SweepStatus simStatus;
|
||||||
|
private SweepCancelForm? simCancelForm;
|
||||||
|
internal SweepInfoViewer? simViewer;
|
||||||
|
|
||||||
|
private readonly Font statusFont;
|
||||||
|
|
||||||
|
public MainForm(Scene? initialScene)
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
|
||||||
|
SetStyle(ControlStyles.UserPaint, true);
|
||||||
|
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
|
||||||
|
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
|
||||||
|
|
||||||
|
Graphics tempG = CreateGraphics();
|
||||||
|
scalingFactor = tempG.DpiX / 96;
|
||||||
|
tempG.Dispose();
|
||||||
|
|
||||||
|
baseFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!;
|
||||||
|
sceneFolder = Path.Combine(baseFolder, "./scenes/");
|
||||||
|
Directory.CreateDirectory(sceneFolder);
|
||||||
|
FileOpener.InitialDirectory = sceneFolder;
|
||||||
|
|
||||||
|
Scene = initialScene ?? Scene.Default;
|
||||||
|
|
||||||
|
statusFont = new("Segoe UI", 10);
|
||||||
|
MenuRunCancel.Enabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Int2 PlotToScreen(Float2 plot)
|
||||||
|
{
|
||||||
|
int menuHeight = Menu.Height;
|
||||||
|
int buffer = (int)(20 * scalingFactor);
|
||||||
|
|
||||||
|
double bufferX, bufferY, maxPix, pixPerUnit;
|
||||||
|
double clientAspect = (double)(ClientRectangle.Height - menuHeight - buffer * 2) / (ClientRectangle.Width - buffer * 2),
|
||||||
|
sceneAspect = Scene.Height / Scene.Width;
|
||||||
|
|
||||||
|
if (clientAspect > sceneAspect)
|
||||||
|
{
|
||||||
|
// Client is taller than scene, use width as max.
|
||||||
|
maxPix = ClientRectangle.Width - 2 * buffer;
|
||||||
|
pixPerUnit = maxPix / Scene.Width;
|
||||||
|
|
||||||
|
bufferX = buffer;
|
||||||
|
bufferY = (ClientRectangle.Height + menuHeight - Scene.Height * pixPerUnit) * 0.5f;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Client is wider than scene, use height as max.
|
||||||
|
maxPix = ClientRectangle.Height - menuHeight - 2 * buffer;
|
||||||
|
pixPerUnit = maxPix / Scene.Height;
|
||||||
|
|
||||||
|
bufferX = (ClientRectangle.Width - Scene.Width * pixPerUnit) * 0.5f;
|
||||||
|
bufferY = buffer + menuHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ((int)(plot.x * pixPerUnit + bufferX),
|
||||||
|
(int)((Scene.Height - plot.y) * pixPerUnit + bufferY));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnPaint(PaintEventArgs e)
|
||||||
|
{
|
||||||
|
Graphics g = e.Graphics;
|
||||||
|
g.SmoothingMode = SmoothingMode.HighQuality;
|
||||||
|
Pen pen = new(Color.Black, scalingFactor);
|
||||||
|
SolidBrush fill = new(Color.Black);
|
||||||
|
|
||||||
|
const int fillAlpha = 64;
|
||||||
|
|
||||||
|
// Draw components.
|
||||||
|
foreach (ISceneObject obj in Scene.Objects)
|
||||||
|
{
|
||||||
|
if (obj is SceneRect objRect)
|
||||||
|
{
|
||||||
|
pen.Color = Color.Green;
|
||||||
|
fill.Color = Color.FromArgb(fillAlpha, pen.Color);
|
||||||
|
Int2 rectFrom = PlotToScreen(objRect.From), rectTo = PlotToScreen(objRect.To);
|
||||||
|
int minX = int.Min(rectFrom.x, rectTo.x), sizeX = MathE.Absolute(rectFrom.x - rectTo.x),
|
||||||
|
minY = int.Min(rectFrom.y, rectTo.y), sizeY = MathE.Absolute(rectFrom.y - rectTo.y);
|
||||||
|
Rectangle rect = new(new Point(minX, minY), new Size(sizeX, sizeY));
|
||||||
|
g.FillRectangle(fill, rect);
|
||||||
|
g.DrawRectangle(pen, rect);
|
||||||
|
}
|
||||||
|
else if (obj is SceneTri objTri)
|
||||||
|
{
|
||||||
|
pen.Color = Color.Orange;
|
||||||
|
fill.Color = Color.FromArgb(fillAlpha, pen.Color);
|
||||||
|
Int2 triA = PlotToScreen(objTri.A),
|
||||||
|
triB = PlotToScreen(objTri.B),
|
||||||
|
triC = PlotToScreen(objTri.C);
|
||||||
|
g.FillPolygon(fill, [triA, triB, triC]);
|
||||||
|
g.DrawPolygon(pen, [triA, triB, triC]);
|
||||||
|
}
|
||||||
|
else if (obj is SceneEllipse objEllipse)
|
||||||
|
{
|
||||||
|
pen.Color = Color.Purple;
|
||||||
|
fill.Color = Color.FromArgb(fillAlpha, pen.Color);
|
||||||
|
Int2 min = PlotToScreen(objEllipse.Position - objEllipse.Size * 0.5),
|
||||||
|
max = PlotToScreen(objEllipse.Position + objEllipse.Size * 0.5);
|
||||||
|
Rectangle ellipseRect = new(min, max - min);
|
||||||
|
g.FillEllipse(fill, ellipseRect);
|
||||||
|
g.DrawEllipse(pen, ellipseRect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw scene border.
|
||||||
|
pen.Color = Color.Blue;
|
||||||
|
pen.Width = scalingFactor * 2;
|
||||||
|
Int2 sceneMin = PlotToScreen((0, Scene.Height)), sceneMax = PlotToScreen((Scene.Width, 0));
|
||||||
|
g.DrawRectangle(pen, new Rectangle(sceneMin, sceneMax - sceneMin));
|
||||||
|
|
||||||
|
// Draw starting position.
|
||||||
|
int startPosSize = (int)(6 * scalingFactor);
|
||||||
|
pen.Color = Color.Red;
|
||||||
|
pen.Width = scalingFactor;
|
||||||
|
fill.Color = Color.FromArgb(fillAlpha, pen.Color);
|
||||||
|
Int2 startPos = PlotToScreen(Scene.StartAt);
|
||||||
|
startPos.x -= startPosSize;
|
||||||
|
startPos.y -= startPosSize;
|
||||||
|
Rectangle startRect = new(startPos, Int2.One * startPosSize * 2);
|
||||||
|
g.FillEllipse(fill, startRect);
|
||||||
|
g.DrawEllipse(pen, startRect);
|
||||||
|
|
||||||
|
// Draw ending position.
|
||||||
|
pen.Color = Color.Lime;
|
||||||
|
pen.Width = scalingFactor;
|
||||||
|
fill.Color = Color.FromArgb(fillAlpha, pen.Color);
|
||||||
|
Int2 endPos = PlotToScreen(Scene.EndAt);
|
||||||
|
endPos.x -= startPosSize;
|
||||||
|
endPos.y -= startPosSize;
|
||||||
|
Rectangle endRect = new(endPos, Int2.One * startPosSize * 2);
|
||||||
|
g.FillEllipse(fill, endRect);
|
||||||
|
g.DrawEllipse(pen, endRect);
|
||||||
|
|
||||||
|
// If there's a trail, draw it.
|
||||||
|
pen.Color = Color.Red;
|
||||||
|
if (simResult is not null)
|
||||||
|
{
|
||||||
|
Point[] points = new Point[simResult.Trail.Count];
|
||||||
|
for (int i = 0; i < points.Length; i++)
|
||||||
|
{
|
||||||
|
points[i] = PlotToScreen(simResult.Trail[i]);
|
||||||
|
}
|
||||||
|
g.DrawLines(pen, points);
|
||||||
|
|
||||||
|
// Draw X at end point (if it's a crash and not a finish).
|
||||||
|
if (simResult.EndDistanceSquared >= SweepParameters!.Tolerance * SweepParameters.Tolerance)
|
||||||
|
{
|
||||||
|
Int2 end = points[^1];
|
||||||
|
PointF[] xShape = [
|
||||||
|
new Float2(-5, -5) * scalingFactor + end,
|
||||||
|
new Float2(5, 5) * scalingFactor + end,
|
||||||
|
new Float2(0, 0) * scalingFactor + end,
|
||||||
|
new Float2(-5, 5) * scalingFactor + end,
|
||||||
|
new Float2(5, -5) * scalingFactor + end,
|
||||||
|
];
|
||||||
|
g.DrawLines(pen, xShape);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string message = simStatus switch
|
||||||
|
{
|
||||||
|
SweepStatus.NoSweep => "No Sweep",
|
||||||
|
SweepStatus.Sweeping => $"Sweeping... Best {simResult?.StartingConditions.StartAngle:0.000} deg, {simResult?.StartingConditions.StartVelocity:0.0} m/s",
|
||||||
|
SweepStatus.FinishedSweep => $"Done Sweeping. Best {simResult?.StartingConditions.StartAngle:0.000} deg, {simResult?.StartingConditions.StartVelocity:0.0} m/s",
|
||||||
|
SweepStatus.CancelledSweep => $"Cancelled Sweep. Best {simResult?.StartingConditions.StartAngle:0.000} deg, {simResult?.StartingConditions.StartVelocity:0.0} m/s",
|
||||||
|
_ => "???",
|
||||||
|
};
|
||||||
|
fill.Color = Color.Blue;
|
||||||
|
SizeF size = g.MeasureString(message, statusFont);
|
||||||
|
const float spacing = 1;
|
||||||
|
g.DrawString(message, statusFont, fill, new PointF(spacing * scalingFactor, ClientRectangle.Height - size.Height - spacing * scalingFactor));
|
||||||
|
|
||||||
|
e.Dispose();
|
||||||
|
}
|
||||||
|
protected override void OnClientSizeChanged(EventArgs e)
|
||||||
|
{
|
||||||
|
base.OnClientSizeChanged(e);
|
||||||
|
Invalidate(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ResetSceneData()
|
||||||
|
{
|
||||||
|
simCancel?.Cancel();
|
||||||
|
|
||||||
|
simResult = null;
|
||||||
|
simCancel = null;
|
||||||
|
SweepParameters = null;
|
||||||
|
simStatus = SweepStatus.NoSweep;
|
||||||
|
simViewer?.Close();
|
||||||
|
Invalidate(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void MenuFileNew_Click(object? sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (!TryCancelSweep()) return;
|
||||||
|
|
||||||
|
if (!Scene.HasBeenSaved)
|
||||||
|
{
|
||||||
|
DialogResult result = MessageBox.Show(
|
||||||
|
"Are you sure you want to discard your changes?", "Lose changes?",
|
||||||
|
MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
|
||||||
|
|
||||||
|
if (result == DialogResult.No) return;
|
||||||
|
}
|
||||||
|
Scene = Scene.Default;
|
||||||
|
ResetSceneData();
|
||||||
|
}
|
||||||
|
private void MenuFileOpen_Click(object? sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (!TryCancelSweep()) return;
|
||||||
|
|
||||||
|
DialogResult result;
|
||||||
|
if (!Scene.HasBeenSaved)
|
||||||
|
{
|
||||||
|
result = MessageBox.Show(
|
||||||
|
"Are you sure you want to discard your changes?", "Lose changes?",
|
||||||
|
MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
|
||||||
|
|
||||||
|
if (result == DialogResult.No) return;
|
||||||
|
}
|
||||||
|
result = FileOpener.ShowDialog();
|
||||||
|
if (result == DialogResult.Cancel) return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Scene = Scene.Read(FileOpener.FileName);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
MessageBox.Show($"Error opening scene file: {ex.GetType().Name}");
|
||||||
|
}
|
||||||
|
ResetSceneData();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void MenuRunSweep_Click(object? sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (!TryCancelSweep()) return;
|
||||||
|
|
||||||
|
SweepParametersForm param = new(this);
|
||||||
|
DialogResult result = param.ShowDialog();
|
||||||
|
if (result == DialogResult.Cancel) return;
|
||||||
|
|
||||||
|
SweepParameters = param.Result;
|
||||||
|
simCancel = new();
|
||||||
|
simStatus = SweepStatus.Sweeping;
|
||||||
|
MenuRunCancel.Enabled = true;
|
||||||
|
simViewer ??= new SweepInfoViewer(this);
|
||||||
|
simViewer.UncompleteSweep();
|
||||||
|
simViewer.Show();
|
||||||
|
Task.Run(() => SweepSimulation(SweepParameters, simCancel.Token));
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryCancelSweep()
|
||||||
|
{
|
||||||
|
if (simStatus == SweepStatus.Sweeping && simCancel is not null)
|
||||||
|
{
|
||||||
|
SweepCancelForm form = new();
|
||||||
|
simCancelForm = form;
|
||||||
|
DialogResult result = form.ShowDialog();
|
||||||
|
if (result == DialogResult.No) return false;
|
||||||
|
|
||||||
|
simCancel?.Cancel();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SweepSimulation(SweepParameters param, CancellationToken token)
|
||||||
|
{
|
||||||
|
Float2 diff = param.Scene.EndAt - param.Scene.StartAt;
|
||||||
|
double minAngle = Math.Atan2(diff.y, diff.x) * Constants.Pi / 180,
|
||||||
|
maxAngle = Constants.Pi / 2,
|
||||||
|
angleStep = param.AngleDelta * Constants.Pi / 180;
|
||||||
|
|
||||||
|
double closest = double.MaxValue, tolSquared = param.Tolerance * param.Tolerance;
|
||||||
|
bool end = false;
|
||||||
|
int angleSteps = (int)((maxAngle - minAngle) / angleStep);
|
||||||
|
int steps = 0;
|
||||||
|
simViewer?.SetMaxIters(angleSteps);
|
||||||
|
for (double ang = minAngle; ang <= maxAngle; ang += angleStep)
|
||||||
|
{
|
||||||
|
for (double vel = param.SpeedMin; vel <= param.SpeedMax; vel += param.SpeedDelta)
|
||||||
|
{
|
||||||
|
if (token.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
end = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
SimulationParameters simParams = new()
|
||||||
|
{
|
||||||
|
DeltaTime = param.TimeDelta,
|
||||||
|
Gravity = param.Gravity,
|
||||||
|
StartAngle = ang,
|
||||||
|
StartVelocity = vel,
|
||||||
|
Scene = Scene,
|
||||||
|
ToleranceSquared = tolSquared,
|
||||||
|
ObjectRadius = param.ObjectRadius,
|
||||||
|
DragCoefficient = param.DragCoefficient,
|
||||||
|
Mass = param.Mass,
|
||||||
|
AirDensity = param.AirDensity,
|
||||||
|
GenerateTable = param.FileMode != ResultsFileMode.None
|
||||||
|
};
|
||||||
|
SimulationResult result = SimulateTrajectory(simParams, token);
|
||||||
|
if (result.EndDistanceSquared < closest)
|
||||||
|
{
|
||||||
|
Invoke(() =>
|
||||||
|
{
|
||||||
|
simResult = result;
|
||||||
|
});
|
||||||
|
Invalidate(true);
|
||||||
|
closest = result.EndDistanceSquared;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (end) break;
|
||||||
|
simViewer?.SetCurrentIters(steps);
|
||||||
|
steps++;
|
||||||
|
}
|
||||||
|
simCancel = null;
|
||||||
|
simStatus = token.IsCancellationRequested ? SweepStatus.CancelledSweep : SweepStatus.FinishedSweep;
|
||||||
|
if (simCancelForm is not null)
|
||||||
|
{
|
||||||
|
simCancelForm.DialogResult = DialogResult.No;
|
||||||
|
simCancelForm.Close();
|
||||||
|
}
|
||||||
|
MenuRunCancel.Enabled = false;
|
||||||
|
simViewer?.Invoke(() => simViewer?.CompleteSweep(simResult!));
|
||||||
|
Invalidate(true);
|
||||||
|
}
|
||||||
|
private static SimulationResult SimulateTrajectory(SimulationParameters param, CancellationToken token)
|
||||||
|
{
|
||||||
|
Float2 pos = param.Scene.StartAt;
|
||||||
|
Float2 vel = (Math.Cos(param.StartAngle) * param.StartVelocity,
|
||||||
|
Math.Sin(param.StartAngle) * param.StartVelocity);
|
||||||
|
Float2 gravity = (0, param.Gravity);
|
||||||
|
double halfArea = 0.5 * param.ObjectRadius * param.ObjectRadius * Constants.Pi;
|
||||||
|
|
||||||
|
SimulationResult result = new(param);
|
||||||
|
double trailPointsPerSecond = 5;
|
||||||
|
int ticksPerTrailPoint = (int)(1 / (trailPointsPerSecond * param.DeltaTime));
|
||||||
|
|
||||||
|
if (param.GenerateTable) result.Table = [];
|
||||||
|
|
||||||
|
int ticks = 0;
|
||||||
|
double time = 0;
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
Float2 air = (halfArea * param.DragCoefficient * param.AirDensity * vel.x * vel.x,
|
||||||
|
halfArea * param.DragCoefficient * param.AirDensity * vel.y * vel.y);
|
||||||
|
|
||||||
|
Float2 acc = gravity;
|
||||||
|
if (param.Mass > 0)
|
||||||
|
{
|
||||||
|
air /= param.Mass;
|
||||||
|
acc.x -= air.x * Math.Sign(vel.x);
|
||||||
|
acc.y -= air.y * Math.Sign(vel.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (param.GenerateTable) result.Table!.Add(new(pos, vel, acc));
|
||||||
|
|
||||||
|
if (pos.x < 0 || pos.x >= param.Scene.Width ||
|
||||||
|
pos.y < 0 || pos.y >= param.Scene.Height)
|
||||||
|
{
|
||||||
|
result.Trail.Add(pos);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (token.IsCancellationRequested) break;
|
||||||
|
|
||||||
|
bool collide = false;
|
||||||
|
for (int i = 0; i < param.Scene.Objects.Count; i++)
|
||||||
|
{
|
||||||
|
if (param.Scene.Objects[i].Contains(pos))
|
||||||
|
{
|
||||||
|
collide = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (collide)
|
||||||
|
{
|
||||||
|
result.Trail.Add(pos);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Float2 diff = param.Scene.EndAt - pos;
|
||||||
|
result.EndDistanceSquared = diff.x * diff.x + diff.y * diff.y;
|
||||||
|
if (result.EndDistanceSquared <= param.ToleranceSquared)
|
||||||
|
{
|
||||||
|
result.Trail.Add(pos);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ticks % ticksPerTrailPoint == 0) result.Trail.Add(pos);
|
||||||
|
|
||||||
|
pos += vel * param.DeltaTime;
|
||||||
|
vel += acc * param.DeltaTime;
|
||||||
|
|
||||||
|
time += param.DeltaTime;
|
||||||
|
}
|
||||||
|
result.StartingConditions.StartAngle *= 180 / Constants.Pi;
|
||||||
|
result.EndSpeed = vel.Magnitude;
|
||||||
|
result.Duration = time;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void MenuRunCancel_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
simCancel?.Cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum SweepStatus
|
||||||
|
{
|
||||||
|
NoSweep,
|
||||||
|
Sweeping,
|
||||||
|
FinishedSweep,
|
||||||
|
CancelledSweep
|
||||||
|
}
|
||||||
|
}
|
||||||
126
AirTrajectoryBuilder/AirTrajectoryBuilder/Forms/MainForm.resx
Normal file
126
AirTrajectoryBuilder/AirTrajectoryBuilder/Forms/MainForm.resx
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<metadata name="Menu.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
|
<value>17, 17</value>
|
||||||
|
</metadata>
|
||||||
|
<metadata name="FileOpener.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
|
<value>157, 17</value>
|
||||||
|
</metadata>
|
||||||
|
</root>
|
||||||
87
AirTrajectoryBuilder/AirTrajectoryBuilder/Forms/SweepCancelForm.Designer.cs
generated
Normal file
87
AirTrajectoryBuilder/AirTrajectoryBuilder/Forms/SweepCancelForm.Designer.cs
generated
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
namespace AirTrajectoryBuilder.Forms
|
||||||
|
{
|
||||||
|
partial class SweepCancelForm
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Required designer variable.
|
||||||
|
/// </summary>
|
||||||
|
private System.ComponentModel.IContainer components = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clean up any resources being used.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing && (components != null))
|
||||||
|
{
|
||||||
|
components.Dispose();
|
||||||
|
}
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Windows Form Designer generated code
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Required method for Designer support - do not modify
|
||||||
|
/// the contents of this method with the code editor.
|
||||||
|
/// </summary>
|
||||||
|
private void InitializeComponent()
|
||||||
|
{
|
||||||
|
MessageLabel = new System.Windows.Forms.Label();
|
||||||
|
YesButton = new System.Windows.Forms.Button();
|
||||||
|
button2 = new System.Windows.Forms.Button();
|
||||||
|
SuspendLayout();
|
||||||
|
//
|
||||||
|
// MessageLabel
|
||||||
|
//
|
||||||
|
MessageLabel.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
|
||||||
|
MessageLabel.Location = new System.Drawing.Point(12, 12);
|
||||||
|
MessageLabel.Name = "MessageLabel";
|
||||||
|
MessageLabel.Size = new System.Drawing.Size(637, 135);
|
||||||
|
MessageLabel.TabIndex = 0;
|
||||||
|
MessageLabel.Text = "Are you sure you want to cancel the sweep?";
|
||||||
|
MessageLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
|
||||||
|
//
|
||||||
|
// YesButton
|
||||||
|
//
|
||||||
|
YesButton.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left;
|
||||||
|
YesButton.DialogResult = System.Windows.Forms.DialogResult.Yes;
|
||||||
|
YesButton.Location = new System.Drawing.Point(178, 150);
|
||||||
|
YesButton.Name = "YesButton";
|
||||||
|
YesButton.Size = new System.Drawing.Size(150, 46);
|
||||||
|
YesButton.TabIndex = 1;
|
||||||
|
YesButton.Text = "Yes";
|
||||||
|
YesButton.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// button2
|
||||||
|
//
|
||||||
|
button2.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right;
|
||||||
|
button2.DialogResult = System.Windows.Forms.DialogResult.No;
|
||||||
|
button2.Location = new System.Drawing.Point(334, 150);
|
||||||
|
button2.Name = "button2";
|
||||||
|
button2.Size = new System.Drawing.Size(150, 46);
|
||||||
|
button2.TabIndex = 2;
|
||||||
|
button2.Text = "No";
|
||||||
|
button2.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// SweepCancelForm
|
||||||
|
//
|
||||||
|
AutoScaleDimensions = new System.Drawing.SizeF(13F, 32F);
|
||||||
|
AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
|
ClientSize = new System.Drawing.Size(661, 208);
|
||||||
|
Controls.Add(button2);
|
||||||
|
Controls.Add(YesButton);
|
||||||
|
Controls.Add(MessageLabel);
|
||||||
|
Name = "SweepCancelForm";
|
||||||
|
Text = "Cancel the Sweep?";
|
||||||
|
ResumeLayout(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private System.Windows.Forms.Label MessageLabel;
|
||||||
|
private System.Windows.Forms.Button YesButton;
|
||||||
|
private System.Windows.Forms.Button button2;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace AirTrajectoryBuilder.Forms;
|
||||||
|
|
||||||
|
public partial class SweepCancelForm : Form
|
||||||
|
{
|
||||||
|
public SweepCancelForm()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,120 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
</root>
|
||||||
99
AirTrajectoryBuilder/AirTrajectoryBuilder/Forms/SweepInfoViewer.Designer.cs
generated
Normal file
99
AirTrajectoryBuilder/AirTrajectoryBuilder/Forms/SweepInfoViewer.Designer.cs
generated
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
namespace AirTrajectoryBuilder.Forms
|
||||||
|
{
|
||||||
|
partial class SweepInfoViewer
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Required designer variable.
|
||||||
|
/// </summary>
|
||||||
|
private System.ComponentModel.IContainer components = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clean up any resources being used.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing && (components != null))
|
||||||
|
{
|
||||||
|
components.Dispose();
|
||||||
|
}
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Windows Form Designer generated code
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Required method for Designer support - do not modify
|
||||||
|
/// the contents of this method with the code editor.
|
||||||
|
/// </summary>
|
||||||
|
private void InitializeComponent()
|
||||||
|
{
|
||||||
|
SweepProgress = new System.Windows.Forms.ProgressBar();
|
||||||
|
ProgressLabel = new System.Windows.Forms.Label();
|
||||||
|
ResultsPanel = new System.Windows.Forms.Panel();
|
||||||
|
ResultsLabel = new System.Windows.Forms.Label();
|
||||||
|
ResultsPanel.SuspendLayout();
|
||||||
|
SuspendLayout();
|
||||||
|
//
|
||||||
|
// SweepProgress
|
||||||
|
//
|
||||||
|
SweepProgress.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
|
||||||
|
SweepProgress.Location = new System.Drawing.Point(12, 229);
|
||||||
|
SweepProgress.Name = "SweepProgress";
|
||||||
|
SweepProgress.Size = new System.Drawing.Size(673, 20);
|
||||||
|
SweepProgress.Style = System.Windows.Forms.ProgressBarStyle.Continuous;
|
||||||
|
SweepProgress.TabIndex = 0;
|
||||||
|
SweepProgress.Value = 50;
|
||||||
|
//
|
||||||
|
// ProgressLabel
|
||||||
|
//
|
||||||
|
ProgressLabel.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
|
||||||
|
ProgressLabel.Location = new System.Drawing.Point(12, 194);
|
||||||
|
ProgressLabel.Name = "ProgressLabel";
|
||||||
|
ProgressLabel.Size = new System.Drawing.Size(673, 32);
|
||||||
|
ProgressLabel.TabIndex = 1;
|
||||||
|
ProgressLabel.Text = "Conducting Sweep...";
|
||||||
|
ProgressLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
|
||||||
|
//
|
||||||
|
// ResultsPanel
|
||||||
|
//
|
||||||
|
ResultsPanel.AutoScroll = true;
|
||||||
|
ResultsPanel.Controls.Add(ResultsLabel);
|
||||||
|
ResultsPanel.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||||
|
ResultsPanel.Location = new System.Drawing.Point(0, 0);
|
||||||
|
ResultsPanel.Name = "ResultsPanel";
|
||||||
|
ResultsPanel.Size = new System.Drawing.Size(697, 405);
|
||||||
|
ResultsPanel.TabIndex = 2;
|
||||||
|
ResultsPanel.Visible = false;
|
||||||
|
//
|
||||||
|
// ResultsLabel
|
||||||
|
//
|
||||||
|
ResultsLabel.Location = new System.Drawing.Point(12, 9);
|
||||||
|
ResultsLabel.Name = "ResultsLabel";
|
||||||
|
ResultsLabel.Size = new System.Drawing.Size(682, 387);
|
||||||
|
ResultsLabel.TabIndex = 0;
|
||||||
|
ResultsLabel.Text = "label1";
|
||||||
|
//
|
||||||
|
// SweepInfoViewer
|
||||||
|
//
|
||||||
|
AutoScaleDimensions = new System.Drawing.SizeF(13F, 32F);
|
||||||
|
AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
|
ClientSize = new System.Drawing.Size(697, 405);
|
||||||
|
Controls.Add(ResultsPanel);
|
||||||
|
Controls.Add(ProgressLabel);
|
||||||
|
Controls.Add(SweepProgress);
|
||||||
|
Name = "SweepInfoViewer";
|
||||||
|
StartPosition = System.Windows.Forms.FormStartPosition.Manual;
|
||||||
|
Text = "Simulation Results";
|
||||||
|
ResultsPanel.ResumeLayout(false);
|
||||||
|
ResumeLayout(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private System.Windows.Forms.ProgressBar SweepProgress;
|
||||||
|
private System.Windows.Forms.Label ProgressLabel;
|
||||||
|
private System.Windows.Forms.Panel ResultsPanel;
|
||||||
|
private System.Windows.Forms.Label ResultsLabel;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,97 @@
|
|||||||
|
using AirTrajectoryBuilder.ObjectModels;
|
||||||
|
using System;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace AirTrajectoryBuilder.Forms;
|
||||||
|
|
||||||
|
public partial class SweepInfoViewer : Form
|
||||||
|
{
|
||||||
|
private readonly MainForm mainForm;
|
||||||
|
private SimulationResult? results;
|
||||||
|
|
||||||
|
public SweepInfoViewer(MainForm mainForm)
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
ResultsPanel.Visible = false;
|
||||||
|
this.mainForm = mainForm;
|
||||||
|
|
||||||
|
Location =
|
||||||
|
new Point(mainForm.Location.X + mainForm.Size.Width,
|
||||||
|
mainForm.Location.Y + (mainForm.Size.Height - Size.Height) / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnClosing(CancelEventArgs e)
|
||||||
|
{
|
||||||
|
if (!mainForm.TryCancelSweep())
|
||||||
|
{
|
||||||
|
e.Cancel = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
base.OnClosing(e);
|
||||||
|
mainForm.simViewer = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetMaxIters(int max)
|
||||||
|
{
|
||||||
|
SweepProgress.Maximum = max;
|
||||||
|
}
|
||||||
|
public void SetCurrentIters(int val)
|
||||||
|
{
|
||||||
|
SweepProgress.Value = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CompleteSweep(SimulationResult best)
|
||||||
|
{
|
||||||
|
results = best;
|
||||||
|
|
||||||
|
SweepProgress.Visible = false;
|
||||||
|
ProgressLabel.Visible = false;
|
||||||
|
|
||||||
|
DisplayResults();
|
||||||
|
}
|
||||||
|
public void UncompleteSweep()
|
||||||
|
{
|
||||||
|
SweepProgress.Visible = true;
|
||||||
|
ProgressLabel.Visible = true;
|
||||||
|
ResultsPanel.Visible = false;
|
||||||
|
Invalidate(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetLabelSize()
|
||||||
|
{
|
||||||
|
ResultsLabel.Location = new Point(0, 0);
|
||||||
|
ResultsLabel.Size = new(ResultsPanel.ClientRectangle.Width,
|
||||||
|
ResultsLabel.PreferredHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnResize(EventArgs e)
|
||||||
|
{
|
||||||
|
base.OnResize(e);
|
||||||
|
SetLabelSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DisplayResults()
|
||||||
|
{
|
||||||
|
ResultsPanel.Visible = true;
|
||||||
|
if (results is null) return;
|
||||||
|
|
||||||
|
ResultsLabel.Text = $"""
|
||||||
|
|
||||||
|
Initial Angle: {results.StartingConditions.StartAngle:0.00} degrees
|
||||||
|
Initial Velocity: {results.StartingConditions.StartVelocity:0.0} m/s
|
||||||
|
Gravity: {results.StartingConditions.Gravity:0.000} m/s^2
|
||||||
|
Delta Time: {results.StartingConditions.DeltaTime:0.000} seconds
|
||||||
|
|
||||||
|
Final Velocity: {results.EndSpeed:0.0} m/s
|
||||||
|
|
||||||
|
Duration: {results.Duration:0.00} seconds
|
||||||
|
|
||||||
|
Error: off by {results.EndDistanceSquared:0.000} meters
|
||||||
|
|
||||||
|
""";
|
||||||
|
SetLabelSize();
|
||||||
|
SetLabelSize(); // ...nice. But required!
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,120 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
</root>
|
||||||
361
AirTrajectoryBuilder/AirTrajectoryBuilder/Forms/SweepParametersForm.Designer.cs
generated
Normal file
361
AirTrajectoryBuilder/AirTrajectoryBuilder/Forms/SweepParametersForm.Designer.cs
generated
Normal file
@ -0,0 +1,361 @@
|
|||||||
|
namespace AirTrajectoryBuilder
|
||||||
|
{
|
||||||
|
partial class SweepParametersForm
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Required designer variable.
|
||||||
|
/// </summary>
|
||||||
|
private System.ComponentModel.IContainer components = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clean up any resources being used.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing && (components != null))
|
||||||
|
{
|
||||||
|
components.Dispose();
|
||||||
|
}
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Windows Form Designer generated code
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Required method for Designer support - do not modify
|
||||||
|
/// the contents of this method with the code editor.
|
||||||
|
/// </summary>
|
||||||
|
private void InitializeComponent()
|
||||||
|
{
|
||||||
|
AngleSweepValue = new System.Windows.Forms.TextBox();
|
||||||
|
AngleSweepLabel = new System.Windows.Forms.Label();
|
||||||
|
SpeedMinLabel = new System.Windows.Forms.Label();
|
||||||
|
SpeedMinValue = new System.Windows.Forms.TextBox();
|
||||||
|
SpeedMaxLabel = new System.Windows.Forms.Label();
|
||||||
|
SpeedDeltaLabel = new System.Windows.Forms.Label();
|
||||||
|
SpeedMaxValue = new System.Windows.Forms.TextBox();
|
||||||
|
SpeedDeltaValue = new System.Windows.Forms.TextBox();
|
||||||
|
RunButton = new System.Windows.Forms.Button();
|
||||||
|
GravityLabel = new System.Windows.Forms.Label();
|
||||||
|
GravityValue = new System.Windows.Forms.TextBox();
|
||||||
|
TimeDeltaLabel = new System.Windows.Forms.Label();
|
||||||
|
TimeDeltaValue = new System.Windows.Forms.TextBox();
|
||||||
|
CancelButton = new System.Windows.Forms.Button();
|
||||||
|
ProjectileMotionLabel = new System.Windows.Forms.Label();
|
||||||
|
AirTrajectoryLabel = new System.Windows.Forms.Label();
|
||||||
|
ObjectRadiusValue = new System.Windows.Forms.TextBox();
|
||||||
|
ObjectRadiusLabel = new System.Windows.Forms.Label();
|
||||||
|
MassValue = new System.Windows.Forms.TextBox();
|
||||||
|
MassLabel = new System.Windows.Forms.Label();
|
||||||
|
AirDensityValue = new System.Windows.Forms.TextBox();
|
||||||
|
AirDensityLabel = new System.Windows.Forms.Label();
|
||||||
|
DragCoefficientValue = new System.Windows.Forms.TextBox();
|
||||||
|
DragCoefficientLabel = new System.Windows.Forms.Label();
|
||||||
|
ResultsLabel = new System.Windows.Forms.Label();
|
||||||
|
FileOutputLabel = new System.Windows.Forms.Label();
|
||||||
|
FileOutputValue = new System.Windows.Forms.ComboBox();
|
||||||
|
SuspendLayout();
|
||||||
|
//
|
||||||
|
// AngleSweepValue
|
||||||
|
//
|
||||||
|
AngleSweepValue.Location = new System.Drawing.Point(312, 122);
|
||||||
|
AngleSweepValue.Name = "AngleSweepValue";
|
||||||
|
AngleSweepValue.Size = new System.Drawing.Size(101, 39);
|
||||||
|
AngleSweepValue.TabIndex = 0;
|
||||||
|
//
|
||||||
|
// AngleSweepLabel
|
||||||
|
//
|
||||||
|
AngleSweepLabel.Location = new System.Drawing.Point(82, 122);
|
||||||
|
AngleSweepLabel.Name = "AngleSweepLabel";
|
||||||
|
AngleSweepLabel.Size = new System.Drawing.Size(224, 39);
|
||||||
|
AngleSweepLabel.TabIndex = 1;
|
||||||
|
AngleSweepLabel.Text = "Angle Sweep Delta";
|
||||||
|
AngleSweepLabel.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
|
||||||
|
//
|
||||||
|
// SpeedMinLabel
|
||||||
|
//
|
||||||
|
SpeedMinLabel.Location = new System.Drawing.Point(12, 168);
|
||||||
|
SpeedMinLabel.Name = "SpeedMinLabel";
|
||||||
|
SpeedMinLabel.Size = new System.Drawing.Size(159, 39);
|
||||||
|
SpeedMinLabel.TabIndex = 2;
|
||||||
|
SpeedMinLabel.Text = "Speed Min";
|
||||||
|
SpeedMinLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
|
||||||
|
//
|
||||||
|
// SpeedMinValue
|
||||||
|
//
|
||||||
|
SpeedMinValue.Location = new System.Drawing.Point(36, 210);
|
||||||
|
SpeedMinValue.Name = "SpeedMinValue";
|
||||||
|
SpeedMinValue.Size = new System.Drawing.Size(101, 39);
|
||||||
|
SpeedMinValue.TabIndex = 3;
|
||||||
|
//
|
||||||
|
// SpeedMaxLabel
|
||||||
|
//
|
||||||
|
SpeedMaxLabel.Location = new System.Drawing.Point(177, 168);
|
||||||
|
SpeedMaxLabel.Name = "SpeedMaxLabel";
|
||||||
|
SpeedMaxLabel.Size = new System.Drawing.Size(159, 39);
|
||||||
|
SpeedMaxLabel.TabIndex = 4;
|
||||||
|
SpeedMaxLabel.Text = "Speed Max";
|
||||||
|
SpeedMaxLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
|
||||||
|
//
|
||||||
|
// SpeedDeltaLabel
|
||||||
|
//
|
||||||
|
SpeedDeltaLabel.Location = new System.Drawing.Point(342, 168);
|
||||||
|
SpeedDeltaLabel.Name = "SpeedDeltaLabel";
|
||||||
|
SpeedDeltaLabel.Size = new System.Drawing.Size(159, 39);
|
||||||
|
SpeedDeltaLabel.TabIndex = 5;
|
||||||
|
SpeedDeltaLabel.Text = "Sweep Delta";
|
||||||
|
SpeedDeltaLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
|
||||||
|
//
|
||||||
|
// SpeedMaxValue
|
||||||
|
//
|
||||||
|
SpeedMaxValue.Location = new System.Drawing.Point(204, 210);
|
||||||
|
SpeedMaxValue.Name = "SpeedMaxValue";
|
||||||
|
SpeedMaxValue.Size = new System.Drawing.Size(101, 39);
|
||||||
|
SpeedMaxValue.TabIndex = 6;
|
||||||
|
//
|
||||||
|
// SpeedDeltaValue
|
||||||
|
//
|
||||||
|
SpeedDeltaValue.Location = new System.Drawing.Point(371, 210);
|
||||||
|
SpeedDeltaValue.Name = "SpeedDeltaValue";
|
||||||
|
SpeedDeltaValue.Size = new System.Drawing.Size(101, 39);
|
||||||
|
SpeedDeltaValue.TabIndex = 7;
|
||||||
|
//
|
||||||
|
// RunButton
|
||||||
|
//
|
||||||
|
RunButton.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left;
|
||||||
|
RunButton.DialogResult = System.Windows.Forms.DialogResult.OK;
|
||||||
|
RunButton.Location = new System.Drawing.Point(198, 707);
|
||||||
|
RunButton.Name = "RunButton";
|
||||||
|
RunButton.Size = new System.Drawing.Size(150, 46);
|
||||||
|
RunButton.TabIndex = 8;
|
||||||
|
RunButton.Text = "Sweep";
|
||||||
|
RunButton.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// GravityLabel
|
||||||
|
//
|
||||||
|
GravityLabel.Location = new System.Drawing.Point(138, 258);
|
||||||
|
GravityLabel.Name = "GravityLabel";
|
||||||
|
GravityLabel.Size = new System.Drawing.Size(113, 39);
|
||||||
|
GravityLabel.TabIndex = 10;
|
||||||
|
GravityLabel.Text = "Gravity";
|
||||||
|
GravityLabel.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
|
||||||
|
//
|
||||||
|
// GravityValue
|
||||||
|
//
|
||||||
|
GravityValue.Location = new System.Drawing.Point(257, 258);
|
||||||
|
GravityValue.Name = "GravityValue";
|
||||||
|
GravityValue.Size = new System.Drawing.Size(101, 39);
|
||||||
|
GravityValue.TabIndex = 9;
|
||||||
|
//
|
||||||
|
// TimeDeltaLabel
|
||||||
|
//
|
||||||
|
TimeDeltaLabel.Location = new System.Drawing.Point(131, 75);
|
||||||
|
TimeDeltaLabel.Name = "TimeDeltaLabel";
|
||||||
|
TimeDeltaLabel.Size = new System.Drawing.Size(137, 39);
|
||||||
|
TimeDeltaLabel.TabIndex = 12;
|
||||||
|
TimeDeltaLabel.Text = "Time Delta";
|
||||||
|
TimeDeltaLabel.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
|
||||||
|
//
|
||||||
|
// TimeDeltaValue
|
||||||
|
//
|
||||||
|
TimeDeltaValue.Location = new System.Drawing.Point(274, 75);
|
||||||
|
TimeDeltaValue.Name = "TimeDeltaValue";
|
||||||
|
TimeDeltaValue.Size = new System.Drawing.Size(101, 39);
|
||||||
|
TimeDeltaValue.TabIndex = 11;
|
||||||
|
//
|
||||||
|
// CancelButton
|
||||||
|
//
|
||||||
|
CancelButton.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left;
|
||||||
|
CancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
|
||||||
|
CancelButton.Location = new System.Drawing.Point(354, 707);
|
||||||
|
CancelButton.Name = "CancelButton";
|
||||||
|
CancelButton.Size = new System.Drawing.Size(150, 46);
|
||||||
|
CancelButton.TabIndex = 13;
|
||||||
|
CancelButton.Text = "Cancel";
|
||||||
|
CancelButton.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// ProjectileMotionLabel
|
||||||
|
//
|
||||||
|
ProjectileMotionLabel.Font = new System.Drawing.Font("Segoe UI", 10.125F, System.Drawing.FontStyle.Bold);
|
||||||
|
ProjectileMotionLabel.Location = new System.Drawing.Point(12, 9);
|
||||||
|
ProjectileMotionLabel.Name = "ProjectileMotionLabel";
|
||||||
|
ProjectileMotionLabel.Size = new System.Drawing.Size(489, 39);
|
||||||
|
ProjectileMotionLabel.TabIndex = 14;
|
||||||
|
ProjectileMotionLabel.Text = "General Parameters:";
|
||||||
|
ProjectileMotionLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
|
||||||
|
//
|
||||||
|
// AirTrajectoryLabel
|
||||||
|
//
|
||||||
|
AirTrajectoryLabel.Font = new System.Drawing.Font("Segoe UI", 10.125F, System.Drawing.FontStyle.Bold);
|
||||||
|
AirTrajectoryLabel.Location = new System.Drawing.Point(14, 327);
|
||||||
|
AirTrajectoryLabel.Name = "AirTrajectoryLabel";
|
||||||
|
AirTrajectoryLabel.Size = new System.Drawing.Size(489, 39);
|
||||||
|
AirTrajectoryLabel.TabIndex = 15;
|
||||||
|
AirTrajectoryLabel.Text = "Aerodynamics (Optional):";
|
||||||
|
AirTrajectoryLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
|
||||||
|
//
|
||||||
|
// ObjectRadiusValue
|
||||||
|
//
|
||||||
|
ObjectRadiusValue.Location = new System.Drawing.Point(82, 419);
|
||||||
|
ObjectRadiusValue.Name = "ObjectRadiusValue";
|
||||||
|
ObjectRadiusValue.Size = new System.Drawing.Size(101, 39);
|
||||||
|
ObjectRadiusValue.TabIndex = 17;
|
||||||
|
//
|
||||||
|
// ObjectRadiusLabel
|
||||||
|
//
|
||||||
|
ObjectRadiusLabel.Location = new System.Drawing.Point(12, 377);
|
||||||
|
ObjectRadiusLabel.Name = "ObjectRadiusLabel";
|
||||||
|
ObjectRadiusLabel.Size = new System.Drawing.Size(239, 39);
|
||||||
|
ObjectRadiusLabel.TabIndex = 16;
|
||||||
|
ObjectRadiusLabel.Text = "Object Radius";
|
||||||
|
ObjectRadiusLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
|
||||||
|
//
|
||||||
|
// MassValue
|
||||||
|
//
|
||||||
|
MassValue.Location = new System.Drawing.Point(335, 419);
|
||||||
|
MassValue.Name = "MassValue";
|
||||||
|
MassValue.Size = new System.Drawing.Size(101, 39);
|
||||||
|
MassValue.TabIndex = 19;
|
||||||
|
//
|
||||||
|
// MassLabel
|
||||||
|
//
|
||||||
|
MassLabel.Location = new System.Drawing.Point(265, 377);
|
||||||
|
MassLabel.Name = "MassLabel";
|
||||||
|
MassLabel.Size = new System.Drawing.Size(239, 39);
|
||||||
|
MassLabel.TabIndex = 18;
|
||||||
|
MassLabel.Text = "Object Mass";
|
||||||
|
MassLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
|
||||||
|
//
|
||||||
|
// AirDensityValue
|
||||||
|
//
|
||||||
|
AirDensityValue.Location = new System.Drawing.Point(335, 512);
|
||||||
|
AirDensityValue.Name = "AirDensityValue";
|
||||||
|
AirDensityValue.Size = new System.Drawing.Size(101, 39);
|
||||||
|
AirDensityValue.TabIndex = 23;
|
||||||
|
//
|
||||||
|
// AirDensityLabel
|
||||||
|
//
|
||||||
|
AirDensityLabel.Location = new System.Drawing.Point(265, 470);
|
||||||
|
AirDensityLabel.Name = "AirDensityLabel";
|
||||||
|
AirDensityLabel.Size = new System.Drawing.Size(239, 39);
|
||||||
|
AirDensityLabel.TabIndex = 22;
|
||||||
|
AirDensityLabel.Text = "Air Density";
|
||||||
|
AirDensityLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
|
||||||
|
//
|
||||||
|
// DragCoefficientValue
|
||||||
|
//
|
||||||
|
DragCoefficientValue.Location = new System.Drawing.Point(82, 512);
|
||||||
|
DragCoefficientValue.Name = "DragCoefficientValue";
|
||||||
|
DragCoefficientValue.Size = new System.Drawing.Size(101, 39);
|
||||||
|
DragCoefficientValue.TabIndex = 21;
|
||||||
|
//
|
||||||
|
// DragCoefficientLabel
|
||||||
|
//
|
||||||
|
DragCoefficientLabel.Location = new System.Drawing.Point(12, 470);
|
||||||
|
DragCoefficientLabel.Name = "DragCoefficientLabel";
|
||||||
|
DragCoefficientLabel.Size = new System.Drawing.Size(239, 39);
|
||||||
|
DragCoefficientLabel.TabIndex = 20;
|
||||||
|
DragCoefficientLabel.Text = "Drag Coefficient";
|
||||||
|
DragCoefficientLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
|
||||||
|
//
|
||||||
|
// ResultsLabel
|
||||||
|
//
|
||||||
|
ResultsLabel.Font = new System.Drawing.Font("Segoe UI", 10.125F, System.Drawing.FontStyle.Bold);
|
||||||
|
ResultsLabel.Location = new System.Drawing.Point(14, 583);
|
||||||
|
ResultsLabel.Name = "ResultsLabel";
|
||||||
|
ResultsLabel.Size = new System.Drawing.Size(489, 39);
|
||||||
|
ResultsLabel.TabIndex = 24;
|
||||||
|
ResultsLabel.Text = "Results:";
|
||||||
|
ResultsLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
|
||||||
|
//
|
||||||
|
// FileOutputLabel
|
||||||
|
//
|
||||||
|
FileOutputLabel.Location = new System.Drawing.Point(37, 622);
|
||||||
|
FileOutputLabel.Name = "FileOutputLabel";
|
||||||
|
FileOutputLabel.Size = new System.Drawing.Size(156, 64);
|
||||||
|
FileOutputLabel.TabIndex = 25;
|
||||||
|
FileOutputLabel.Text = "File Output";
|
||||||
|
FileOutputLabel.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
|
||||||
|
//
|
||||||
|
// FileOutputValue
|
||||||
|
//
|
||||||
|
FileOutputValue.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
||||||
|
FileOutputValue.FormattingEnabled = true;
|
||||||
|
FileOutputValue.Items.AddRange(new object[] { "None", "Text - Best", "Text - All", "Json - Best", "Json - All", "Binary - Best", "Binary - All" });
|
||||||
|
FileOutputValue.Location = new System.Drawing.Point(199, 635);
|
||||||
|
FileOutputValue.MaxLength = 1;
|
||||||
|
FileOutputValue.Name = "FileOutputValue";
|
||||||
|
FileOutputValue.Size = new System.Drawing.Size(242, 40);
|
||||||
|
FileOutputValue.TabIndex = 26;
|
||||||
|
//
|
||||||
|
// SweepParametersForm
|
||||||
|
//
|
||||||
|
AutoScaleDimensions = new System.Drawing.SizeF(13F, 32F);
|
||||||
|
AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
|
ClientSize = new System.Drawing.Size(516, 765);
|
||||||
|
Controls.Add(FileOutputValue);
|
||||||
|
Controls.Add(FileOutputLabel);
|
||||||
|
Controls.Add(ResultsLabel);
|
||||||
|
Controls.Add(AirDensityValue);
|
||||||
|
Controls.Add(AirDensityLabel);
|
||||||
|
Controls.Add(DragCoefficientValue);
|
||||||
|
Controls.Add(DragCoefficientLabel);
|
||||||
|
Controls.Add(MassValue);
|
||||||
|
Controls.Add(MassLabel);
|
||||||
|
Controls.Add(ObjectRadiusValue);
|
||||||
|
Controls.Add(ObjectRadiusLabel);
|
||||||
|
Controls.Add(AirTrajectoryLabel);
|
||||||
|
Controls.Add(ProjectileMotionLabel);
|
||||||
|
Controls.Add(CancelButton);
|
||||||
|
Controls.Add(TimeDeltaLabel);
|
||||||
|
Controls.Add(TimeDeltaValue);
|
||||||
|
Controls.Add(GravityLabel);
|
||||||
|
Controls.Add(GravityValue);
|
||||||
|
Controls.Add(RunButton);
|
||||||
|
Controls.Add(SpeedDeltaValue);
|
||||||
|
Controls.Add(SpeedMaxValue);
|
||||||
|
Controls.Add(SpeedDeltaLabel);
|
||||||
|
Controls.Add(SpeedMaxLabel);
|
||||||
|
Controls.Add(SpeedMinValue);
|
||||||
|
Controls.Add(SpeedMinLabel);
|
||||||
|
Controls.Add(AngleSweepLabel);
|
||||||
|
Controls.Add(AngleSweepValue);
|
||||||
|
FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
|
||||||
|
Name = "SweepParametersForm";
|
||||||
|
Text = "Set Sweep Parameters";
|
||||||
|
ResumeLayout(false);
|
||||||
|
PerformLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private System.Windows.Forms.TextBox AngleSweepValue;
|
||||||
|
private System.Windows.Forms.Label AngleSweepLabel;
|
||||||
|
private System.Windows.Forms.Label SpeedMinLabel;
|
||||||
|
private System.Windows.Forms.TextBox SpeedMinValue;
|
||||||
|
private System.Windows.Forms.Label SpeedMaxLabel;
|
||||||
|
private System.Windows.Forms.Label SpeedDeltaLabel;
|
||||||
|
private System.Windows.Forms.TextBox SpeedMaxValue;
|
||||||
|
private System.Windows.Forms.TextBox SpeedDeltaValue;
|
||||||
|
private System.Windows.Forms.Button RunButton;
|
||||||
|
private System.Windows.Forms.Label GravityLabel;
|
||||||
|
private System.Windows.Forms.TextBox GravityValue;
|
||||||
|
private System.Windows.Forms.Label TimeDeltaLabel;
|
||||||
|
private System.Windows.Forms.TextBox TimeDeltaValue;
|
||||||
|
private System.Windows.Forms.Button CancelButton;
|
||||||
|
private System.Windows.Forms.Label ProjectileMotionLabel;
|
||||||
|
private System.Windows.Forms.Label AirTrajectoryLabel;
|
||||||
|
private System.Windows.Forms.TextBox ObjectRadiusValue;
|
||||||
|
private System.Windows.Forms.Label ObjectRadiusLabel;
|
||||||
|
private System.Windows.Forms.TextBox MassValue;
|
||||||
|
private System.Windows.Forms.Label MassLabel;
|
||||||
|
private System.Windows.Forms.TextBox AirDensityValue;
|
||||||
|
private System.Windows.Forms.Label AirDensityLabel;
|
||||||
|
private System.Windows.Forms.TextBox DragCoefficientValue;
|
||||||
|
private System.Windows.Forms.Label DragCoefficientLabel;
|
||||||
|
private System.Windows.Forms.Label ResultsLabel;
|
||||||
|
private System.Windows.Forms.Label FileOutputLabel;
|
||||||
|
private System.Windows.Forms.ComboBox FileOutputValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,156 @@
|
|||||||
|
using AirTrajectoryBuilder.ObjectModels;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.IO;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace AirTrajectoryBuilder;
|
||||||
|
|
||||||
|
public partial class SweepParametersForm : Form
|
||||||
|
{
|
||||||
|
private static readonly FileMode[] fileModeValues = Enum.GetValues<FileMode>();
|
||||||
|
|
||||||
|
public double AngleDelta = 0.1,
|
||||||
|
SpeedDelta = 0.5,
|
||||||
|
SpeedMin = 10,
|
||||||
|
SpeedMax = 100,
|
||||||
|
Gravity = -9.81,
|
||||||
|
TimeDelta = 0.01;
|
||||||
|
|
||||||
|
public double ObjectRadius = 0,
|
||||||
|
DragCoefficient = 0,
|
||||||
|
Mass = 0,
|
||||||
|
AirDensity = 1.225;
|
||||||
|
|
||||||
|
public ResultsFileMode FileMode = ResultsFileMode.None;
|
||||||
|
|
||||||
|
private static SweepParameters? previous = null;
|
||||||
|
|
||||||
|
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||||||
|
public SweepParameters Result
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
SweepParameters result = new()
|
||||||
|
{
|
||||||
|
AngleDelta = AngleDelta,
|
||||||
|
SpeedDelta = SpeedDelta,
|
||||||
|
SpeedMin = SpeedMin,
|
||||||
|
SpeedMax = SpeedMax,
|
||||||
|
Gravity = Gravity,
|
||||||
|
TimeDelta = TimeDelta,
|
||||||
|
ObjectRadius = ObjectRadius,
|
||||||
|
DragCoefficient = DragCoefficient,
|
||||||
|
Mass = Mass,
|
||||||
|
AirDensity = AirDensity,
|
||||||
|
Tolerance = 1e-1, // TODO
|
||||||
|
Scene = form.Scene,
|
||||||
|
FileMode = FileMode
|
||||||
|
};
|
||||||
|
previous = result;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
AngleDelta = value.AngleDelta;
|
||||||
|
SpeedDelta = value.SpeedDelta;
|
||||||
|
SpeedMin = value.SpeedMin;
|
||||||
|
SpeedMax = value.SpeedMax;
|
||||||
|
Gravity = value.Gravity;
|
||||||
|
TimeDelta = value.TimeDelta;
|
||||||
|
ObjectRadius = value.ObjectRadius;
|
||||||
|
DragCoefficient = value.DragCoefficient;
|
||||||
|
Mass = value.Mass;
|
||||||
|
AirDensity = value.AirDensity;
|
||||||
|
FileMode = value.FileMode;
|
||||||
|
|
||||||
|
previous = value;
|
||||||
|
SetValues();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private readonly MainForm form;
|
||||||
|
|
||||||
|
public SweepParametersForm(MainForm form)
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
this.form = form;
|
||||||
|
|
||||||
|
AngleSweepValue.Leave += (o, e) =>
|
||||||
|
{
|
||||||
|
if (!double.TryParse(AngleSweepValue.Text, out AngleDelta))
|
||||||
|
AngleSweepValue.Text = AngleDelta.ToString();
|
||||||
|
};
|
||||||
|
SpeedDeltaValue.Leave += (o, e) =>
|
||||||
|
{
|
||||||
|
if (!double.TryParse(SpeedDeltaValue.Text, out SpeedDelta))
|
||||||
|
SpeedDeltaValue.Text = SpeedDelta.ToString();
|
||||||
|
};
|
||||||
|
SpeedMinValue.Leave += (o, e) =>
|
||||||
|
{
|
||||||
|
if (!double.TryParse(SpeedMinValue.Text, out SpeedMin))
|
||||||
|
SpeedMinValue.Text = SpeedMin.ToString();
|
||||||
|
};
|
||||||
|
SpeedMaxValue.Leave += (o, e) =>
|
||||||
|
{
|
||||||
|
if (!double.TryParse(SpeedMaxValue.Text, out SpeedMax))
|
||||||
|
SpeedMaxValue.Text = SpeedMax.ToString();
|
||||||
|
};
|
||||||
|
GravityValue.Leave += (o, e) =>
|
||||||
|
{
|
||||||
|
if (!double.TryParse(GravityValue.Text, out Gravity))
|
||||||
|
GravityValue.Text = Gravity.ToString();
|
||||||
|
};
|
||||||
|
TimeDeltaValue.Leave += (o, e) =>
|
||||||
|
{
|
||||||
|
if (!double.TryParse(TimeDeltaValue.Text, out TimeDelta))
|
||||||
|
TimeDeltaValue.Text = TimeDelta.ToString();
|
||||||
|
};
|
||||||
|
ObjectRadiusValue.Leave += (o, e) =>
|
||||||
|
{
|
||||||
|
if (!double.TryParse(ObjectRadiusValue.Text, out ObjectRadius))
|
||||||
|
ObjectRadiusValue.Text = ObjectRadius.ToString();
|
||||||
|
};
|
||||||
|
MassValue.Leave += (o, e) =>
|
||||||
|
{
|
||||||
|
if (!double.TryParse(MassValue.Text, out Mass))
|
||||||
|
MassValue.Text = Mass.ToString();
|
||||||
|
};
|
||||||
|
DragCoefficientValue.Leave += (o, e) =>
|
||||||
|
{
|
||||||
|
if (!double.TryParse(DragCoefficientValue.Text, out DragCoefficient))
|
||||||
|
DragCoefficientValue.Text = DragCoefficient.ToString();
|
||||||
|
};
|
||||||
|
AirDensityValue.Leave += (o, e) =>
|
||||||
|
{
|
||||||
|
if (!double.TryParse(AirDensityValue.Text, out AirDensity))
|
||||||
|
AirDensityValue.Text = AirDensity.ToString();
|
||||||
|
};
|
||||||
|
FileOutputValue.Leave += (o, e) =>
|
||||||
|
{
|
||||||
|
int index = FileOutputValue.SelectedIndex;
|
||||||
|
if (index < 0 || index >= FileOutputValue.Items.Count)
|
||||||
|
{
|
||||||
|
FileOutputValue.SelectedIndex = (int)FileMode;
|
||||||
|
}
|
||||||
|
else FileMode = (ResultsFileMode)FileOutputValue.SelectedIndex;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (previous is null) SetValues();
|
||||||
|
else Result = previous;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetValues()
|
||||||
|
{
|
||||||
|
AngleSweepValue.Text = AngleDelta.ToString();
|
||||||
|
SpeedDeltaValue.Text = SpeedDelta.ToString();
|
||||||
|
SpeedMinValue.Text = SpeedMin.ToString();
|
||||||
|
SpeedMaxValue.Text = SpeedMax.ToString();
|
||||||
|
GravityValue.Text = Gravity.ToString();
|
||||||
|
TimeDeltaValue.Text = TimeDelta.ToString();
|
||||||
|
ObjectRadiusValue.Text = ObjectRadius.ToString();
|
||||||
|
MassValue.Text = Mass.ToString();
|
||||||
|
DragCoefficientValue.Text = DragCoefficient.ToString();
|
||||||
|
AirDensityValue.Text = AirDensity.ToString();
|
||||||
|
FileOutputValue.SelectedIndex = (int)FileMode;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,120 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
</root>
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
using Nerd_STF.Mathematics;
|
||||||
|
|
||||||
|
namespace AirTrajectoryBuilder.ObjectModels;
|
||||||
|
|
||||||
|
public interface ISceneObject
|
||||||
|
{
|
||||||
|
public bool Contains(Float2 point);
|
||||||
|
public ISceneObject DeepCopy();
|
||||||
|
}
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
namespace AirTrajectoryBuilder.ObjectModels;
|
||||||
|
|
||||||
|
public enum ResultsFileMode
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
TextBest,
|
||||||
|
TextAll,
|
||||||
|
JsonBest,
|
||||||
|
JsonAll,
|
||||||
|
BinaryBest,
|
||||||
|
BinaryAll
|
||||||
|
}
|
||||||
146
AirTrajectoryBuilder/AirTrajectoryBuilder/ObjectModels/Scene.cs
Normal file
146
AirTrajectoryBuilder/AirTrajectoryBuilder/ObjectModels/Scene.cs
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
using Nerd_STF.Mathematics;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace AirTrajectoryBuilder.ObjectModels
|
||||||
|
{
|
||||||
|
public class Scene
|
||||||
|
{
|
||||||
|
public static Scene Default => new()
|
||||||
|
{
|
||||||
|
Width = 100,
|
||||||
|
Height = 60,
|
||||||
|
Objects = [],
|
||||||
|
HasBeenSaved = true,
|
||||||
|
FilePath = null,
|
||||||
|
EndAt = (100, 0)
|
||||||
|
};
|
||||||
|
|
||||||
|
public double Width { get; set; }
|
||||||
|
public double Height { get; set; }
|
||||||
|
|
||||||
|
public Float2 StartAt { get; set; }
|
||||||
|
public Float2 EndAt { get; set; }
|
||||||
|
|
||||||
|
public bool HasBeenSaved { get; set; }
|
||||||
|
public string? FilePath { get; set; }
|
||||||
|
|
||||||
|
public List<ISceneObject> Objects { get; private set; } = [];
|
||||||
|
|
||||||
|
public Scene DeepCopy()
|
||||||
|
{
|
||||||
|
Scene copy = new()
|
||||||
|
{
|
||||||
|
Width = Width,
|
||||||
|
Height = Height,
|
||||||
|
StartAt = StartAt,
|
||||||
|
EndAt = EndAt,
|
||||||
|
HasBeenSaved = HasBeenSaved,
|
||||||
|
FilePath = FilePath,
|
||||||
|
Objects = []
|
||||||
|
};
|
||||||
|
foreach (ISceneObject obj in Objects) copy.Objects.Add(obj.DeepCopy());
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Scene Read(string path)
|
||||||
|
{
|
||||||
|
if (!File.Exists(path)) throw new IOException();
|
||||||
|
StreamReader reader = new(path);
|
||||||
|
|
||||||
|
string? line;
|
||||||
|
Scene? scene = null;
|
||||||
|
while ((line = reader.ReadLine()) is not null)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(line)) continue;
|
||||||
|
string[] parts = line.Split(' ');
|
||||||
|
|
||||||
|
switch (parts[0])
|
||||||
|
{
|
||||||
|
case "Scene":
|
||||||
|
if (parts.Length != 4) throw new IOException();
|
||||||
|
else if (parts[2] != "by") throw new IOException();
|
||||||
|
scene = new()
|
||||||
|
{
|
||||||
|
Width = double.Parse(parts[1]),
|
||||||
|
Height = double.Parse(parts[3]),
|
||||||
|
Objects = [],
|
||||||
|
HasBeenSaved = true,
|
||||||
|
FilePath = path,
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
case "Rect":
|
||||||
|
if (scene is null) throw new IOException();
|
||||||
|
else if (parts.Length != 6) throw new IOException();
|
||||||
|
else if (parts[3] != "to") throw new IOException();
|
||||||
|
SceneRect rect = new()
|
||||||
|
{
|
||||||
|
From = (double.Parse(parts[1]), double.Parse(parts[2])),
|
||||||
|
To = (double.Parse(parts[4]), double.Parse(parts[5]))
|
||||||
|
};
|
||||||
|
scene.Objects.Add(rect);
|
||||||
|
break;
|
||||||
|
case "Tri":
|
||||||
|
if (scene is null) throw new IOException();
|
||||||
|
else if (parts.Length != 9) throw new IOException();
|
||||||
|
else if (parts[3] != "and" || parts[6] != "and") throw new IOException();
|
||||||
|
SceneTri tri = new()
|
||||||
|
{
|
||||||
|
A = (double.Parse(parts[1]), double.Parse(parts[2])),
|
||||||
|
B = (double.Parse(parts[4]), double.Parse(parts[5])),
|
||||||
|
C = (double.Parse(parts[7]), double.Parse(parts[8]))
|
||||||
|
};
|
||||||
|
scene.Objects.Add(tri);
|
||||||
|
break;
|
||||||
|
case "Ellipse":
|
||||||
|
if (scene is null) throw new IOException();
|
||||||
|
else if (parts.Length != 7) throw new IOException();
|
||||||
|
else if (parts[3] != "and" || parts[5] != "by") throw new IOException();
|
||||||
|
SceneEllipse ellipse = new()
|
||||||
|
{
|
||||||
|
Position = (double.Parse(parts[1]), double.Parse(parts[2])),
|
||||||
|
Size = (double.Parse(parts[4]), double.Parse(parts[6]))
|
||||||
|
};
|
||||||
|
scene.Objects.Add(ellipse);
|
||||||
|
break;
|
||||||
|
case "Start":
|
||||||
|
if (scene is null) throw new IOException();
|
||||||
|
else if (parts.Length != 3) throw new IOException();
|
||||||
|
scene.StartAt = (double.Parse(parts[1]), double.Parse(parts[2]));
|
||||||
|
break;
|
||||||
|
case "End":
|
||||||
|
if (scene is null) throw new IOException();
|
||||||
|
else if (parts.Length != 3) throw new IOException();
|
||||||
|
scene.EndAt = (double.Parse(parts[1]), double.Parse(parts[2]));
|
||||||
|
break;
|
||||||
|
default: throw new IOException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
reader.Close();
|
||||||
|
return scene ?? Default;
|
||||||
|
}
|
||||||
|
public void Write()
|
||||||
|
{
|
||||||
|
StreamWriter writer = new(FilePath ?? throw new IOException());
|
||||||
|
|
||||||
|
writer.WriteLine($"Scene {Width} by {Height}\n");
|
||||||
|
foreach (ISceneObject obj in Objects)
|
||||||
|
{
|
||||||
|
if (obj is SceneRect objRect)
|
||||||
|
{
|
||||||
|
writer.WriteLine($"Rect {objRect.From.x} {objRect.From.y} to {objRect.To.x} {objRect.To.y}");
|
||||||
|
}
|
||||||
|
else if (obj is SceneTri objTri)
|
||||||
|
{
|
||||||
|
writer.WriteLine($"Tri {objTri.A.x} {objTri.A.y} and {objTri.B.x} {objTri.B.y} and {objTri.C.x} {objTri.C.y}");
|
||||||
|
}
|
||||||
|
else if (obj is SceneEllipse objEllipse)
|
||||||
|
{
|
||||||
|
writer.WriteLine($"Ellipse {objEllipse.Position.x} {objEllipse.Position.y} and {objEllipse.Size.x} by {objEllipse.Size.y}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
using Nerd_STF.Mathematics;
|
||||||
|
|
||||||
|
namespace AirTrajectoryBuilder.ObjectModels;
|
||||||
|
|
||||||
|
public class SceneEllipse : ISceneObject
|
||||||
|
{
|
||||||
|
public Float2 Position { get; set; }
|
||||||
|
public Float2 Size { get; set; }
|
||||||
|
|
||||||
|
public bool Contains(Float2 point)
|
||||||
|
{
|
||||||
|
Float2 p = point - Position;
|
||||||
|
Float2 delta = p * 2 / Size;
|
||||||
|
|
||||||
|
delta.x *= delta.x;
|
||||||
|
delta.y *= delta.y;
|
||||||
|
return delta.x + delta.y <= 1;
|
||||||
|
}
|
||||||
|
public ISceneObject DeepCopy() => new SceneEllipse()
|
||||||
|
{
|
||||||
|
Position = Position,
|
||||||
|
Size = Size
|
||||||
|
};
|
||||||
|
}
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
using Nerd_STF.Mathematics;
|
||||||
|
|
||||||
|
namespace AirTrajectoryBuilder.ObjectModels;
|
||||||
|
|
||||||
|
public class SceneRect : ISceneObject
|
||||||
|
{
|
||||||
|
public Float2 From { get; set; }
|
||||||
|
public Float2 To { get; set; }
|
||||||
|
|
||||||
|
public bool Contains(Float2 p)
|
||||||
|
{
|
||||||
|
double minX = double.Min(From.x, To.x), maxX = double.Max(From.x, To.x),
|
||||||
|
minY = double.Min(From.y, To.y), maxY = double.Max(From.y, To.y);
|
||||||
|
|
||||||
|
return p.x >= minX && p.x <= maxX &&
|
||||||
|
p.y >= minY && p.y <= maxY;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ISceneObject DeepCopy() => new SceneRect()
|
||||||
|
{
|
||||||
|
From = From,
|
||||||
|
To = To
|
||||||
|
};
|
||||||
|
}
|
||||||
@ -0,0 +1,33 @@
|
|||||||
|
using Nerd_STF.Mathematics;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace AirTrajectoryBuilder.ObjectModels;
|
||||||
|
|
||||||
|
public class SceneTri : ISceneObject
|
||||||
|
{
|
||||||
|
public Float2 A { get; set; }
|
||||||
|
public Float2 B { get; set; }
|
||||||
|
public Float2 C { get; set; }
|
||||||
|
|
||||||
|
private static double Area(Float2 a, Float2 b, Float2 c)
|
||||||
|
{
|
||||||
|
return Math.Abs((a.x * (b.y - c.y) +
|
||||||
|
b.x * (c.y - a.y) +
|
||||||
|
c.x * (a.y - b.y)) * 0.5);
|
||||||
|
}
|
||||||
|
public bool Contains(Float2 p)
|
||||||
|
{
|
||||||
|
double area = Area(A, B, C),
|
||||||
|
a1 = Area(p, B, C),
|
||||||
|
a2 = Area(A, p, C),
|
||||||
|
a3 = Area(A, B, p);
|
||||||
|
return area == a1 + a2 + a3;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ISceneObject DeepCopy() => new SceneTri()
|
||||||
|
{
|
||||||
|
A = A,
|
||||||
|
B = B,
|
||||||
|
C = C
|
||||||
|
};
|
||||||
|
}
|
||||||
@ -0,0 +1,16 @@
|
|||||||
|
namespace AirTrajectoryBuilder.ObjectModels;
|
||||||
|
|
||||||
|
public class SimulationParameters
|
||||||
|
{
|
||||||
|
public required double StartAngle;
|
||||||
|
public required double StartVelocity;
|
||||||
|
public required double DeltaTime;
|
||||||
|
public required double Gravity;
|
||||||
|
public required double ToleranceSquared;
|
||||||
|
public required double ObjectRadius;
|
||||||
|
public required double DragCoefficient;
|
||||||
|
public required double Mass;
|
||||||
|
public required double AirDensity;
|
||||||
|
public required Scene Scene;
|
||||||
|
public required bool GenerateTable;
|
||||||
|
}
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
using Nerd_STF.Mathematics;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace AirTrajectoryBuilder.ObjectModels;
|
||||||
|
|
||||||
|
public class SimulationResult
|
||||||
|
{
|
||||||
|
public double Duration;
|
||||||
|
|
||||||
|
public double EndDistanceSquared;
|
||||||
|
|
||||||
|
public double EndSpeed;
|
||||||
|
|
||||||
|
public List<Float2> Trail = [];
|
||||||
|
public List<TableEntry>? Table = null;
|
||||||
|
|
||||||
|
public SimulationParameters StartingConditions;
|
||||||
|
|
||||||
|
public SimulationResult(SimulationParameters starting)
|
||||||
|
{
|
||||||
|
StartingConditions = starting;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
namespace AirTrajectoryBuilder.ObjectModels;
|
||||||
|
|
||||||
|
public class SweepParameters
|
||||||
|
{
|
||||||
|
public required double AngleDelta, TimeDelta;
|
||||||
|
public required double SpeedMin, SpeedMax, SpeedDelta;
|
||||||
|
public required double Gravity;
|
||||||
|
public required double Tolerance;
|
||||||
|
|
||||||
|
public required double ObjectRadius;
|
||||||
|
public required double DragCoefficient;
|
||||||
|
public required double Mass;
|
||||||
|
public required double AirDensity;
|
||||||
|
|
||||||
|
public required ResultsFileMode FileMode;
|
||||||
|
|
||||||
|
public required Scene Scene;
|
||||||
|
}
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
using Nerd_STF.Mathematics;
|
||||||
|
|
||||||
|
namespace AirTrajectoryBuilder.ObjectModels;
|
||||||
|
|
||||||
|
public record class TableEntry(Float2 Position, Float2 Velocity, Float2 Acceleration);
|
||||||
41
AirTrajectoryBuilder/AirTrajectoryBuilder/Program.cs
Normal file
41
AirTrajectoryBuilder/AirTrajectoryBuilder/Program.cs
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
/**********722871**********
|
||||||
|
* Date: 12/2/2024
|
||||||
|
* Programmer: Kyle Gilbert
|
||||||
|
* Program Name: AirTrajectoryBuilder
|
||||||
|
* Program Description: Sweeps possible launch angles and speeds in a given scene
|
||||||
|
* and applies aerodynamic physics.
|
||||||
|
**************************/
|
||||||
|
|
||||||
|
using AirTrajectoryBuilder.ObjectModels;
|
||||||
|
using System;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace AirTrajectoryBuilder;
|
||||||
|
|
||||||
|
public static class Program
|
||||||
|
{
|
||||||
|
[STAThread]
|
||||||
|
public static void Main(string[] args)
|
||||||
|
{
|
||||||
|
Application.EnableVisualStyles();
|
||||||
|
Application.SetCompatibleTextRenderingDefault(false);
|
||||||
|
Application.SetHighDpiMode(HighDpiMode.SystemAware);
|
||||||
|
|
||||||
|
Scene? scene;
|
||||||
|
if (args.Length > 0)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
scene = Scene.Read(args[0]);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
MessageBox.Show($"Error opening scene file: {ex.GetType().Name}");
|
||||||
|
scene = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else scene = null;
|
||||||
|
|
||||||
|
Application.Run(new MainForm(scene));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -27,7 +27,12 @@ I have about 1-2 weeks for each project. Check the Git commits for specific date
|
|||||||
- Data transfer is automatically encrypted behind the scenes (though the server decrypts it when it gets it).
|
- Data transfer is automatically encrypted behind the scenes (though the server decrypts it when it gets it).
|
||||||
- Allows for as many people to connect as need be.
|
- Allows for as many people to connect as need be.
|
||||||
- The client is somewhat janky, but the server has zero issues from my testing.
|
- The client is somewhat janky, but the server has zero issues from my testing.
|
||||||
- TypingTest
|
- TypingTest/
|
||||||
- A small game I made in like 2 hours. Using a list of words, it picks one at random and the user has to type it out.
|
- A small game I made in like 2 hours. Using a list of words, it picks one at random and the user has to type it out.
|
||||||
- It has a one-minute timer, and highlights the letters you got right.
|
- It has a one-minute timer, and highlights the letters you got right.
|
||||||
- Shows results as characters per minute, words per minute, and accuracy percentage at the end.
|
- Shows results as characters per minute, words per minute, and accuracy percentage at the end.
|
||||||
|
- AirTrajectoryBuilder
|
||||||
|
- A program I wrote that simulates the air trajectory of a projectile. Finished a while ago.
|
||||||
|
- Create a `.sce` file (a somewhat easy to use plain text format)
|
||||||
|
- Nice colors for each object. Scales seamlessly with a higher DPI.
|
||||||
|
- Sweeps possible angles and speeds to try and find the path that brings the ball closest to the end point.
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user