Slope field detail changer works.
This commit is contained in:
parent
8b63bf011e
commit
eea0bba358
@ -16,6 +16,9 @@
|
||||
<Compile Update="Forms\SetZoomForm.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Update="Forms\SlopeFieldDetailForm.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Update="Forms\TranslateForm.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
|
||||
83
Base/Forms/GraphForm.Designer.cs
generated
83
Base/Forms/GraphForm.Designer.cs
generated
@ -55,6 +55,7 @@ namespace Graphing.Forms
|
||||
UpdaterPopupDownloadButton = new Button();
|
||||
UpdaterPopupCloseButton = new Button();
|
||||
UpdaterPopupMessage = new Label();
|
||||
MenuElementsDetail = new ToolStripMenuItem();
|
||||
GraphMenu.SuspendLayout();
|
||||
UpdaterPopup.SuspendLayout();
|
||||
SuspendLayout();
|
||||
@ -63,10 +64,10 @@ namespace Graphing.Forms
|
||||
//
|
||||
ResetViewportButton.Anchor = AnchorStyles.Top | AnchorStyles.Right;
|
||||
ResetViewportButton.Font = new Font("Segoe UI Emoji", 12F, FontStyle.Regular, GraphicsUnit.Point, 0);
|
||||
ResetViewportButton.Location = new Point(739, 20);
|
||||
ResetViewportButton.Margin = new Padding(2, 1, 2, 1);
|
||||
ResetViewportButton.Location = new Point(1372, 43);
|
||||
ResetViewportButton.Margin = new Padding(4, 2, 4, 2);
|
||||
ResetViewportButton.Name = "ResetViewportButton";
|
||||
ResetViewportButton.Size = new Size(34, 30);
|
||||
ResetViewportButton.Size = new Size(63, 64);
|
||||
ResetViewportButton.TabIndex = 0;
|
||||
ResetViewportButton.Text = "🏠";
|
||||
ResetViewportButton.UseVisualStyleBackColor = true;
|
||||
@ -78,8 +79,7 @@ namespace Graphing.Forms
|
||||
GraphMenu.Items.AddRange(new ToolStripItem[] { MenuViewport, MenuElements, MenuOperations, MenuConvert, MenuMisc });
|
||||
GraphMenu.Location = new Point(0, 0);
|
||||
GraphMenu.Name = "GraphMenu";
|
||||
GraphMenu.Padding = new Padding(3, 1, 0, 1);
|
||||
GraphMenu.Size = new Size(780, 24);
|
||||
GraphMenu.Size = new Size(1449, 42);
|
||||
GraphMenu.TabIndex = 1;
|
||||
GraphMenu.Text = "menuStrip1";
|
||||
//
|
||||
@ -87,118 +87,118 @@ namespace Graphing.Forms
|
||||
//
|
||||
MenuViewport.DropDownItems.AddRange(new ToolStripItem[] { ButtonViewportSetZoom, ButtonViewportSetCenter, ButtonViewportReset, ButtonViewportResetWindow });
|
||||
MenuViewport.Name = "MenuViewport";
|
||||
MenuViewport.Size = new Size(66, 22);
|
||||
MenuViewport.Size = new Size(129, 38);
|
||||
MenuViewport.Text = "Viewport";
|
||||
//
|
||||
// ButtonViewportSetZoom
|
||||
//
|
||||
ButtonViewportSetZoom.Name = "ButtonViewportSetZoom";
|
||||
ButtonViewportSetZoom.Size = new Size(174, 22);
|
||||
ButtonViewportSetZoom.Size = new Size(359, 44);
|
||||
ButtonViewportSetZoom.Text = "Set Zoom";
|
||||
ButtonViewportSetZoom.Click += ButtonViewportSetZoom_Click;
|
||||
//
|
||||
// ButtonViewportSetCenter
|
||||
//
|
||||
ButtonViewportSetCenter.Name = "ButtonViewportSetCenter";
|
||||
ButtonViewportSetCenter.Size = new Size(174, 22);
|
||||
ButtonViewportSetCenter.Size = new Size(359, 44);
|
||||
ButtonViewportSetCenter.Text = "Set Center Position";
|
||||
ButtonViewportSetCenter.Click += ButtonViewportSetCenter_Click;
|
||||
//
|
||||
// ButtonViewportReset
|
||||
//
|
||||
ButtonViewportReset.Name = "ButtonViewportReset";
|
||||
ButtonViewportReset.Size = new Size(174, 22);
|
||||
ButtonViewportReset.Size = new Size(359, 44);
|
||||
ButtonViewportReset.Text = "Reset Viewport";
|
||||
ButtonViewportReset.Click += ButtonViewportReset_Click;
|
||||
//
|
||||
// ButtonViewportResetWindow
|
||||
//
|
||||
ButtonViewportResetWindow.Name = "ButtonViewportResetWindow";
|
||||
ButtonViewportResetWindow.Size = new Size(174, 22);
|
||||
ButtonViewportResetWindow.Size = new Size(359, 44);
|
||||
ButtonViewportResetWindow.Text = "Reset Window Size";
|
||||
ButtonViewportResetWindow.Click += ButtonViewportResetWindow_Click;
|
||||
//
|
||||
// MenuElements
|
||||
//
|
||||
MenuElements.DropDownItems.AddRange(new ToolStripItem[] { MenuElementsColors, MenuElementsRemove });
|
||||
MenuElements.DropDownItems.AddRange(new ToolStripItem[] { MenuElementsColors, MenuElementsDetail, MenuElementsRemove });
|
||||
MenuElements.Name = "MenuElements";
|
||||
MenuElements.Size = new Size(67, 22);
|
||||
MenuElements.Size = new Size(131, 38);
|
||||
MenuElements.Text = "Elements";
|
||||
//
|
||||
// MenuElementsColors
|
||||
//
|
||||
MenuElementsColors.Name = "MenuElementsColors";
|
||||
MenuElementsColors.Size = new Size(117, 22);
|
||||
MenuElementsColors.Size = new Size(359, 44);
|
||||
MenuElementsColors.Text = "Colors";
|
||||
//
|
||||
// MenuElementsRemove
|
||||
//
|
||||
MenuElementsRemove.Name = "MenuElementsRemove";
|
||||
MenuElementsRemove.Size = new Size(117, 22);
|
||||
MenuElementsRemove.Size = new Size(359, 44);
|
||||
MenuElementsRemove.Text = "Remove";
|
||||
//
|
||||
// MenuOperations
|
||||
//
|
||||
MenuOperations.DropDownItems.AddRange(new ToolStripItem[] { MenuOperationsDerivative, MenuOperationsIntegral, MenuOperationsTranslate });
|
||||
MenuOperations.Name = "MenuOperations";
|
||||
MenuOperations.Size = new Size(77, 22);
|
||||
MenuOperations.Size = new Size(151, 38);
|
||||
MenuOperations.Text = "Operations";
|
||||
//
|
||||
// MenuOperationsDerivative
|
||||
//
|
||||
MenuOperationsDerivative.Name = "MenuOperationsDerivative";
|
||||
MenuOperationsDerivative.Size = new Size(179, 22);
|
||||
MenuOperationsDerivative.Size = new Size(360, 44);
|
||||
MenuOperationsDerivative.Text = "Compute Derivative";
|
||||
//
|
||||
// MenuOperationsIntegral
|
||||
//
|
||||
MenuOperationsIntegral.Name = "MenuOperationsIntegral";
|
||||
MenuOperationsIntegral.Size = new Size(179, 22);
|
||||
MenuOperationsIntegral.Size = new Size(360, 44);
|
||||
MenuOperationsIntegral.Text = "Compute Integral";
|
||||
//
|
||||
// MenuOperationsTranslate
|
||||
//
|
||||
MenuOperationsTranslate.Name = "MenuOperationsTranslate";
|
||||
MenuOperationsTranslate.Size = new Size(179, 22);
|
||||
MenuOperationsTranslate.Size = new Size(360, 44);
|
||||
MenuOperationsTranslate.Text = "Translate";
|
||||
//
|
||||
// MenuConvert
|
||||
//
|
||||
MenuConvert.DropDownItems.AddRange(new ToolStripItem[] { MenuConvertEquation, MenuConvertSlopeField });
|
||||
MenuConvert.Name = "MenuConvert";
|
||||
MenuConvert.Size = new Size(61, 22);
|
||||
MenuConvert.Size = new Size(118, 38);
|
||||
MenuConvert.Text = "Convert";
|
||||
//
|
||||
// MenuConvertEquation
|
||||
//
|
||||
MenuConvertEquation.Name = "MenuConvertEquation";
|
||||
MenuConvertEquation.Size = new Size(146, 22);
|
||||
MenuConvertEquation.Size = new Size(297, 44);
|
||||
MenuConvertEquation.Text = "To Equation";
|
||||
//
|
||||
// MenuConvertSlopeField
|
||||
//
|
||||
MenuConvertSlopeField.Name = "MenuConvertSlopeField";
|
||||
MenuConvertSlopeField.Size = new Size(146, 22);
|
||||
MenuConvertSlopeField.Size = new Size(297, 44);
|
||||
MenuConvertSlopeField.Text = "To Slope Field";
|
||||
//
|
||||
// MenuMisc
|
||||
//
|
||||
MenuMisc.DropDownItems.AddRange(new ToolStripItem[] { MenuMiscCaches, MiscMenuPreload });
|
||||
MenuMisc.Name = "MenuMisc";
|
||||
MenuMisc.Size = new Size(44, 22);
|
||||
MenuMisc.Size = new Size(83, 38);
|
||||
MenuMisc.Text = "Misc";
|
||||
//
|
||||
// MenuMiscCaches
|
||||
//
|
||||
MenuMiscCaches.Name = "MenuMiscCaches";
|
||||
MenuMiscCaches.Size = new Size(150, 22);
|
||||
MenuMiscCaches.Size = new Size(299, 44);
|
||||
MenuMiscCaches.Text = "View Caches";
|
||||
MenuMiscCaches.Click += MenuMiscCaches_Click;
|
||||
//
|
||||
// MiscMenuPreload
|
||||
//
|
||||
MiscMenuPreload.Name = "MiscMenuPreload";
|
||||
MiscMenuPreload.Size = new Size(150, 22);
|
||||
MiscMenuPreload.Size = new Size(299, 44);
|
||||
MiscMenuPreload.Text = "Preload Cache";
|
||||
MiscMenuPreload.Click += MiscMenuPreload_Click;
|
||||
//
|
||||
@ -210,18 +210,20 @@ namespace Graphing.Forms
|
||||
UpdaterPopup.Controls.Add(UpdaterPopupDownloadButton);
|
||||
UpdaterPopup.Controls.Add(UpdaterPopupCloseButton);
|
||||
UpdaterPopup.Controls.Add(UpdaterPopupMessage);
|
||||
UpdaterPopup.Location = new Point(520, 371);
|
||||
UpdaterPopup.Location = new Point(966, 791);
|
||||
UpdaterPopup.Margin = new Padding(6, 6, 6, 6);
|
||||
UpdaterPopup.Name = "UpdaterPopup";
|
||||
UpdaterPopup.Size = new Size(261, 55);
|
||||
UpdaterPopup.Size = new Size(483, 115);
|
||||
UpdaterPopup.TabIndex = 2;
|
||||
UpdaterPopup.Visible = false;
|
||||
//
|
||||
// UpdaterPopupDownloadButton
|
||||
//
|
||||
UpdaterPopupDownloadButton.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
|
||||
UpdaterPopupDownloadButton.Location = new Point(181, 27);
|
||||
UpdaterPopupDownloadButton.Location = new Point(336, 58);
|
||||
UpdaterPopupDownloadButton.Margin = new Padding(6, 6, 6, 6);
|
||||
UpdaterPopupDownloadButton.Name = "UpdaterPopupDownloadButton";
|
||||
UpdaterPopupDownloadButton.Size = new Size(75, 23);
|
||||
UpdaterPopupDownloadButton.Size = new Size(139, 49);
|
||||
UpdaterPopupDownloadButton.TabIndex = 2;
|
||||
UpdaterPopupDownloadButton.Text = "Visit";
|
||||
UpdaterPopupDownloadButton.UseVisualStyleBackColor = true;
|
||||
@ -229,10 +231,10 @@ namespace Graphing.Forms
|
||||
// UpdaterPopupCloseButton
|
||||
//
|
||||
UpdaterPopupCloseButton.Anchor = AnchorStyles.Top | AnchorStyles.Right;
|
||||
UpdaterPopupCloseButton.Location = new Point(234, 1);
|
||||
UpdaterPopupCloseButton.Margin = new Padding(1);
|
||||
UpdaterPopupCloseButton.Location = new Point(435, 2);
|
||||
UpdaterPopupCloseButton.Margin = new Padding(2, 2, 2, 2);
|
||||
UpdaterPopupCloseButton.Name = "UpdaterPopupCloseButton";
|
||||
UpdaterPopupCloseButton.Size = new Size(24, 24);
|
||||
UpdaterPopupCloseButton.Size = new Size(45, 51);
|
||||
UpdaterPopupCloseButton.TabIndex = 1;
|
||||
UpdaterPopupCloseButton.Text = "X";
|
||||
UpdaterPopupCloseButton.UseVisualStyleBackColor = true;
|
||||
@ -242,23 +244,29 @@ namespace Graphing.Forms
|
||||
//
|
||||
UpdaterPopupMessage.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left;
|
||||
UpdaterPopupMessage.Font = new Font("Segoe UI", 9.75F, FontStyle.Bold, GraphicsUnit.Point, 0);
|
||||
UpdaterPopupMessage.Location = new Point(3, 3);
|
||||
UpdaterPopupMessage.Margin = new Padding(3);
|
||||
UpdaterPopupMessage.Location = new Point(6, 6);
|
||||
UpdaterPopupMessage.Margin = new Padding(6, 6, 6, 6);
|
||||
UpdaterPopupMessage.Name = "UpdaterPopupMessage";
|
||||
UpdaterPopupMessage.Size = new Size(228, 47);
|
||||
UpdaterPopupMessage.Size = new Size(423, 100);
|
||||
UpdaterPopupMessage.TabIndex = 0;
|
||||
UpdaterPopupMessage.Text = "A <type> update is available!\r\nA.B.C → E.F.G";
|
||||
//
|
||||
// MenuElementsDetail
|
||||
//
|
||||
MenuElementsDetail.Name = "MenuElementsDetail";
|
||||
MenuElementsDetail.Size = new Size(359, 44);
|
||||
MenuElementsDetail.Text = "Detail";
|
||||
//
|
||||
// GraphForm
|
||||
//
|
||||
AutoScaleDimensions = new SizeF(7F, 15F);
|
||||
AutoScaleDimensions = new SizeF(13F, 32F);
|
||||
AutoScaleMode = AutoScaleMode.Font;
|
||||
ClientSize = new Size(780, 425);
|
||||
ClientSize = new Size(1449, 907);
|
||||
Controls.Add(UpdaterPopup);
|
||||
Controls.Add(ResetViewportButton);
|
||||
Controls.Add(GraphMenu);
|
||||
MainMenuStrip = GraphMenu;
|
||||
Margin = new Padding(2, 1, 2, 1);
|
||||
Margin = new Padding(4, 2, 4, 2);
|
||||
Name = "GraphForm";
|
||||
Text = "GraphFormBase";
|
||||
GraphMenu.ResumeLayout(false);
|
||||
@ -294,5 +302,6 @@ namespace Graphing.Forms
|
||||
private Label UpdaterPopupMessage;
|
||||
private Button UpdaterPopupCloseButton;
|
||||
private Button UpdaterPopupDownloadButton;
|
||||
private ToolStripMenuItem MenuElementsDetail;
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,5 @@
|
||||
using Graphing.Abstract;
|
||||
using Graphing.Graphables;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
@ -444,9 +445,38 @@ public partial class GraphForm : Form
|
||||
RegenerateMenuItems();
|
||||
}
|
||||
|
||||
private readonly Dictionary<SlopeField, SlopeFieldDetailForm> sfDetailForms = [];
|
||||
private void ChangeSlopeFieldDetail(SlopeField sf)
|
||||
{
|
||||
if (sfDetailForms.TryGetValue(sf, out SlopeFieldDetailForm? preexistingForm))
|
||||
{
|
||||
preexistingForm.Focus();
|
||||
return;
|
||||
}
|
||||
|
||||
SlopeFieldDetailForm detailForm = new(this, sf)
|
||||
{
|
||||
StartPosition = FormStartPosition.Manual
|
||||
};
|
||||
sfDetailForms.Add(sf, detailForm);
|
||||
|
||||
detailForm.Location = new Point(Location.X + ClientRectangle.Width + 10,
|
||||
Location.Y + (ClientRectangle.Height - detailForm.ClientRectangle.Height) / 2);
|
||||
|
||||
if (detailForm.Location.X + detailForm.Width > Screen.FromControl(this).WorkingArea.Width)
|
||||
{
|
||||
detailForm.StartPosition = FormStartPosition.WindowsDefaultLocation;
|
||||
}
|
||||
detailForm.TopMost = true;
|
||||
detailForm.Show();
|
||||
|
||||
detailForm.FormClosed += (o, e) => sfDetailForms.Remove(sf);
|
||||
}
|
||||
|
||||
private void RegenerateMenuItems()
|
||||
{
|
||||
MenuElementsColors.DropDownItems.Clear();
|
||||
MenuElementsDetail.DropDownItems.Clear();
|
||||
MenuElementsRemove.DropDownItems.Clear();
|
||||
MenuOperationsDerivative.DropDownItems.Clear();
|
||||
MenuOperationsIntegral.DropDownItems.Clear();
|
||||
@ -474,6 +504,17 @@ public partial class GraphForm : Form
|
||||
removeItem.Click += (o, e) => Ungraph(able);
|
||||
MenuElementsRemove.DropDownItems.Add(removeItem);
|
||||
|
||||
if (able is SlopeField sf)
|
||||
{
|
||||
ToolStripMenuItem sfDetailItem = new()
|
||||
{
|
||||
ForeColor = able.Color,
|
||||
Text = able.Name
|
||||
};
|
||||
sfDetailItem.Click += (o, e) => ChangeSlopeFieldDetail(sf);
|
||||
MenuElementsDetail.DropDownItems.Add(sfDetailItem);
|
||||
}
|
||||
|
||||
if (able is IDerivable derivable)
|
||||
{
|
||||
ToolStripMenuItem derivativeItem = new()
|
||||
|
||||
147
Base/Forms/SlopeFieldDetailForm.Designer.cs
generated
Normal file
147
Base/Forms/SlopeFieldDetailForm.Designer.cs
generated
Normal file
@ -0,0 +1,147 @@
|
||||
namespace Graphing.Forms
|
||||
{
|
||||
partial class SlopeFieldDetailForm
|
||||
{
|
||||
/// <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()
|
||||
{
|
||||
Message = new System.Windows.Forms.Label();
|
||||
TrackSlopeDetail = new System.Windows.Forms.TrackBar();
|
||||
MinDetailBox = new System.Windows.Forms.TextBox();
|
||||
MaxDetailBox = new System.Windows.Forms.TextBox();
|
||||
CurrentDetailBox = new System.Windows.Forms.TextBox();
|
||||
IncrementButton = new System.Windows.Forms.Button();
|
||||
DecrementButton = new System.Windows.Forms.Button();
|
||||
((System.ComponentModel.ISupportInitialize)TrackSlopeDetail).BeginInit();
|
||||
SuspendLayout();
|
||||
//
|
||||
// Message
|
||||
//
|
||||
Message.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
|
||||
Message.Location = new System.Drawing.Point(119, 25);
|
||||
Message.Margin = new System.Windows.Forms.Padding(110);
|
||||
Message.Name = "Message";
|
||||
Message.Size = new System.Drawing.Size(516, 109);
|
||||
Message.TabIndex = 1;
|
||||
Message.Text = "Change the Detail of %name%\r\nA higher value means more lines per unit.";
|
||||
Message.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
|
||||
//
|
||||
// TrackSlopeDetail
|
||||
//
|
||||
TrackSlopeDetail.Anchor = System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
|
||||
TrackSlopeDetail.LargeChange = 250;
|
||||
TrackSlopeDetail.Location = new System.Drawing.Point(59, 158);
|
||||
TrackSlopeDetail.Margin = new System.Windows.Forms.Padding(50);
|
||||
TrackSlopeDetail.Maximum = 1000;
|
||||
TrackSlopeDetail.Name = "TrackSlopeDetail";
|
||||
TrackSlopeDetail.Size = new System.Drawing.Size(636, 90);
|
||||
TrackSlopeDetail.SmallChange = 0;
|
||||
TrackSlopeDetail.TabIndex = 0;
|
||||
TrackSlopeDetail.TickFrequency = 0;
|
||||
TrackSlopeDetail.TickStyle = System.Windows.Forms.TickStyle.Both;
|
||||
TrackSlopeDetail.Scroll += TrackSlopeDetail_Scroll;
|
||||
//
|
||||
// MinDetailBox
|
||||
//
|
||||
MinDetailBox.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
MinDetailBox.Location = new System.Drawing.Point(12, 228);
|
||||
MinDetailBox.Name = "MinDetailBox";
|
||||
MinDetailBox.Size = new System.Drawing.Size(100, 39);
|
||||
MinDetailBox.TabIndex = 2;
|
||||
//
|
||||
// MaxDetailBox
|
||||
//
|
||||
MaxDetailBox.Anchor = System.Windows.Forms.AnchorStyles.Right;
|
||||
MaxDetailBox.Location = new System.Drawing.Point(642, 228);
|
||||
MaxDetailBox.Name = "MaxDetailBox";
|
||||
MaxDetailBox.Size = new System.Drawing.Size(100, 39);
|
||||
MaxDetailBox.TabIndex = 3;
|
||||
MaxDetailBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
|
||||
//
|
||||
// CurrentDetailBox
|
||||
//
|
||||
CurrentDetailBox.Anchor = System.Windows.Forms.AnchorStyles.None;
|
||||
CurrentDetailBox.Location = new System.Drawing.Point(330, 228);
|
||||
CurrentDetailBox.Name = "CurrentDetailBox";
|
||||
CurrentDetailBox.Size = new System.Drawing.Size(100, 39);
|
||||
CurrentDetailBox.TabIndex = 4;
|
||||
CurrentDetailBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
|
||||
//
|
||||
// IncrementButton
|
||||
//
|
||||
IncrementButton.Anchor = System.Windows.Forms.AnchorStyles.None;
|
||||
IncrementButton.Font = new System.Drawing.Font("Segoe UI", 7.875F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, 0);
|
||||
IncrementButton.Location = new System.Drawing.Point(436, 228);
|
||||
IncrementButton.Name = "IncrementButton";
|
||||
IncrementButton.Size = new System.Drawing.Size(40, 40);
|
||||
IncrementButton.TabIndex = 5;
|
||||
IncrementButton.Text = "+";
|
||||
IncrementButton.UseVisualStyleBackColor = true;
|
||||
IncrementButton.Click += IncrementButton_Click;
|
||||
//
|
||||
// DecrementButton
|
||||
//
|
||||
DecrementButton.Anchor = System.Windows.Forms.AnchorStyles.None;
|
||||
DecrementButton.Font = new System.Drawing.Font("Segoe UI", 7.875F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, 0);
|
||||
DecrementButton.Location = new System.Drawing.Point(284, 228);
|
||||
DecrementButton.Name = "DecrementButton";
|
||||
DecrementButton.Size = new System.Drawing.Size(40, 40);
|
||||
DecrementButton.TabIndex = 6;
|
||||
DecrementButton.Text = "-";
|
||||
DecrementButton.UseVisualStyleBackColor = true;
|
||||
DecrementButton.Click += DecrementButton_Click;
|
||||
//
|
||||
// SlopeFieldDetailForm
|
||||
//
|
||||
AutoScaleDimensions = new System.Drawing.SizeF(13F, 32F);
|
||||
AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
ClientSize = new System.Drawing.Size(754, 282);
|
||||
Controls.Add(DecrementButton);
|
||||
Controls.Add(IncrementButton);
|
||||
Controls.Add(CurrentDetailBox);
|
||||
Controls.Add(MaxDetailBox);
|
||||
Controls.Add(MinDetailBox);
|
||||
Controls.Add(Message);
|
||||
Controls.Add(TrackSlopeDetail);
|
||||
FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
|
||||
Name = "SlopeFieldDetailForm";
|
||||
Text = "Change Slope Field Detail";
|
||||
((System.ComponentModel.ISupportInitialize)TrackSlopeDetail).EndInit();
|
||||
ResumeLayout(false);
|
||||
PerformLayout();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.Label Message;
|
||||
private System.Windows.Forms.TrackBar TrackSlopeDetail;
|
||||
private System.Windows.Forms.TextBox MinDetailBox;
|
||||
private System.Windows.Forms.TextBox MaxDetailBox;
|
||||
private System.Windows.Forms.TextBox CurrentDetailBox;
|
||||
private System.Windows.Forms.Button IncrementButton;
|
||||
private System.Windows.Forms.Button DecrementButton;
|
||||
}
|
||||
}
|
||||
130
Base/Forms/SlopeFieldDetailForm.cs
Normal file
130
Base/Forms/SlopeFieldDetailForm.cs
Normal file
@ -0,0 +1,130 @@
|
||||
using Graphing.Graphables;
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Graphing.Forms;
|
||||
|
||||
public partial class SlopeFieldDetailForm : Form
|
||||
{
|
||||
private readonly GraphForm refForm;
|
||||
private readonly SlopeField slopeField;
|
||||
|
||||
private double minDetail, maxDetail;
|
||||
|
||||
public SlopeFieldDetailForm(GraphForm form, SlopeField sf)
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
refForm = form;
|
||||
slopeField = sf;
|
||||
|
||||
refForm.Paint += (o, e) => RedeclareValues();
|
||||
RedeclareValues();
|
||||
|
||||
TrackSlopeDetail.KeyDown += (o, e) =>
|
||||
{
|
||||
if (e.KeyCode == Keys.Right) IncrementButton_Click(o, e);
|
||||
else if (e.KeyCode == Keys.Left) DecrementButton_Click(o, e);
|
||||
};
|
||||
|
||||
MinDetailBox.Leave += MinDetailBox_Finish;
|
||||
MinDetailBox.KeyDown += (o, e) =>
|
||||
{
|
||||
if (e.KeyCode == Keys.Enter) MinDetailBox_Finish(o, e);
|
||||
};
|
||||
MaxDetailBox.Leave += MaxDetailBox_Finish;
|
||||
MaxDetailBox.KeyDown += (o, e) =>
|
||||
{
|
||||
if (e.KeyCode == Keys.Enter) MaxDetailBox_Finish(o, e);
|
||||
};
|
||||
CurrentDetailBox.Leave += CurrentDetailBox_Finish;
|
||||
CurrentDetailBox.KeyDown += (o, e) =>
|
||||
{
|
||||
if (e.KeyCode == Keys.Enter) CurrentDetailBox_Finish(o, e);
|
||||
};
|
||||
|
||||
minDetail = sf.Detail / 2;
|
||||
maxDetail = sf.Detail * 2;
|
||||
|
||||
Message.Text = Message.Text.Replace("%name%", sf.Name);
|
||||
}
|
||||
|
||||
// Exponential interpolations are better than simple lerps here since
|
||||
// we're scaling a multiple rather than an additive.
|
||||
private double Interp(double t)
|
||||
{
|
||||
// This is weird. I don't like the +1s and -1s, I don't think I wrote this right.
|
||||
// But it seems to get the job done.
|
||||
return minDetail + Math.Pow(2, t * Math.Log2(maxDetail - minDetail + 1)) - 1;
|
||||
}
|
||||
private double InverseInterp(double c)
|
||||
{
|
||||
return Math.Log2(c - minDetail + 1) / Math.Log2(maxDetail - minDetail + 1);
|
||||
}
|
||||
|
||||
private void RedeclareValues()
|
||||
{
|
||||
double detail = slopeField.Detail;
|
||||
if (detail < minDetail) minDetail = detail;
|
||||
else if (detail > maxDetail) maxDetail = detail;
|
||||
|
||||
double t = InverseInterp(detail);
|
||||
TrackSlopeDetail.Value = (int)(TrackSlopeDetail.Minimum + t * (TrackSlopeDetail.Maximum - TrackSlopeDetail.Minimum));
|
||||
|
||||
MinDetailBox.Text = $"{minDetail:0.00}";
|
||||
MaxDetailBox.Text = $"{maxDetail:0.00}";
|
||||
CurrentDetailBox.Text = $"{detail:0.00}";
|
||||
}
|
||||
|
||||
private void TrackSlopeDetail_Scroll(object? sender, EventArgs e)
|
||||
{
|
||||
double t = (double)(TrackSlopeDetail.Value - TrackSlopeDetail.Minimum) / (TrackSlopeDetail.Maximum - TrackSlopeDetail.Minimum);
|
||||
double newDetail = Interp(t);
|
||||
|
||||
slopeField.Detail = newDetail;
|
||||
refForm.Invalidate(false);
|
||||
}
|
||||
private void MinDetailBox_Finish(object? sender, EventArgs e)
|
||||
{
|
||||
if (double.TryParse(MinDetailBox.Text, out double newMinDetail))
|
||||
{
|
||||
minDetail = newMinDetail;
|
||||
if (minDetail > slopeField.Detail) slopeField.Detail = newMinDetail;
|
||||
}
|
||||
refForm.Invalidate(false);
|
||||
}
|
||||
private void MaxDetailBox_Finish(object? sender, EventArgs e)
|
||||
{
|
||||
if (double.TryParse(MaxDetailBox.Text, out double newMaxDetail))
|
||||
{
|
||||
maxDetail = newMaxDetail;
|
||||
if (maxDetail < slopeField.Detail) slopeField.Detail = newMaxDetail;
|
||||
}
|
||||
refForm.Invalidate(false);
|
||||
}
|
||||
private void CurrentDetailBox_Finish(object? sender, EventArgs e)
|
||||
{
|
||||
if (double.TryParse(CurrentDetailBox.Text, out double newDetail))
|
||||
{
|
||||
if (newDetail < minDetail) minDetail = newDetail;
|
||||
else if (newDetail > maxDetail) maxDetail = newDetail;
|
||||
slopeField.Detail = newDetail;
|
||||
}
|
||||
refForm.Invalidate(false);
|
||||
}
|
||||
|
||||
private void IncrementButton_Click(object? sender, EventArgs e)
|
||||
{
|
||||
double newDetail = slopeField.Detail * 1.0625f;
|
||||
if (newDetail > maxDetail) maxDetail = newDetail;
|
||||
slopeField.Detail = newDetail;
|
||||
refForm.Invalidate(false);
|
||||
}
|
||||
private void DecrementButton_Click(object? sender, EventArgs e)
|
||||
{
|
||||
double newDetail = slopeField.Detail / 1.0625f;
|
||||
if (newDetail < minDetail) minDetail = newDetail;
|
||||
slopeField.Detail = newDetail;
|
||||
refForm.Invalidate(false);
|
||||
}
|
||||
}
|
||||
120
Base/Forms/SlopeFieldDetailForm.resx
Normal file
120
Base/Forms/SlopeFieldDetailForm.resx
Normal file
@ -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>
|
||||
@ -10,9 +10,24 @@ public class SlopeField : Graphable
|
||||
{
|
||||
private static int slopeFieldNum;
|
||||
|
||||
protected readonly SlopeFieldsDelegate equ;
|
||||
protected readonly double detail;
|
||||
public double Detail
|
||||
{
|
||||
get => _detail;
|
||||
set
|
||||
{
|
||||
if (Math.Abs(value - Detail) >= 1e-4)
|
||||
{
|
||||
// When changing detail, we need to regenerate all
|
||||
// the lines. Inefficient, I know. Might be optimized
|
||||
// in a future update.
|
||||
EraseCache();
|
||||
}
|
||||
_detail = value;
|
||||
}
|
||||
}
|
||||
private double _detail;
|
||||
|
||||
protected readonly SlopeFieldsDelegate equ;
|
||||
protected readonly List<(Float2, GraphLine)> cache;
|
||||
|
||||
public SlopeField(double detail, SlopeFieldsDelegate equ)
|
||||
@ -21,13 +36,13 @@ public class SlopeField : Graphable
|
||||
Name = $"Slope Field {slopeFieldNum}";
|
||||
|
||||
this.equ = equ;
|
||||
this.detail = detail;
|
||||
_detail = detail;
|
||||
cache = [];
|
||||
}
|
||||
|
||||
public override IEnumerable<IGraphPart> GetItemsToRender(in GraphForm graph)
|
||||
{
|
||||
double step = 1 / detail;
|
||||
double step = 1 / _detail;
|
||||
double epsilon = step * 0.5;
|
||||
List<IGraphPart> lines = [];
|
||||
|
||||
@ -49,7 +64,7 @@ public class SlopeField : Graphable
|
||||
|
||||
protected GraphLine MakeSlopeLine(Float2 position, double slope)
|
||||
{
|
||||
double size = detail;
|
||||
double size = _detail;
|
||||
|
||||
double dirX = size, dirY = slope * size;
|
||||
double magnitude = Math.Sqrt(dirX * dirX + dirY * dirY);
|
||||
@ -79,17 +94,17 @@ public class SlopeField : Graphable
|
||||
return result;
|
||||
}
|
||||
|
||||
public override Graphable ShallowCopy() => new SlopeField(detail, equ);
|
||||
public override Graphable ShallowCopy() => new SlopeField(_detail, equ);
|
||||
|
||||
public override void EraseCache() => cache.Clear();
|
||||
public override long GetCacheBytes() => cache.Count * 48;
|
||||
|
||||
public override bool ShouldSelectGraphable(in GraphForm graph, Float2 graphMousePos, double factor)
|
||||
{
|
||||
Float2 nearestPos = new(Math.Round(graphMousePos.x * detail) / detail,
|
||||
Math.Round(graphMousePos.y * detail) / detail);
|
||||
Float2 nearestPos = new(Math.Round(graphMousePos.x * _detail) / _detail,
|
||||
Math.Round(graphMousePos.y * _detail) / _detail);
|
||||
|
||||
double epsilon = 1 / (detail * 2.0);
|
||||
double epsilon = 1 / (_detail * 2.0);
|
||||
GraphLine line = GetFromCache(epsilon, nearestPos.x, nearestPos.y);
|
||||
double slope = (line.b.y - line.a.y) / (line.b.x - line.a.x);
|
||||
|
||||
@ -110,10 +125,10 @@ public class SlopeField : Graphable
|
||||
}
|
||||
public override IEnumerable<IGraphPart> GetSelectionItemsToRender(in GraphForm graph, Float2 graphMousePos)
|
||||
{
|
||||
Float2 nearestPos = new(Math.Round(graphMousePos.x * detail) / detail,
|
||||
Math.Round(graphMousePos.y * detail) / detail);
|
||||
Float2 nearestPos = new(Math.Round(graphMousePos.x * _detail) / _detail,
|
||||
Math.Round(graphMousePos.y * _detail) / _detail);
|
||||
|
||||
double epsilon = 1 / (detail * 2.0);
|
||||
double epsilon = 1 / (_detail * 2.0);
|
||||
GraphLine line = GetFromCache(epsilon, nearestPos.x, nearestPos.y);
|
||||
double slope = (line.b.y - line.a.y) / (line.b.x - line.a.x);
|
||||
|
||||
@ -130,9 +145,9 @@ public class SlopeField : Graphable
|
||||
|
||||
public override void Preload(Float2 xRange, Float2 yRange, double step)
|
||||
{
|
||||
for (double x = Math.Ceiling(xRange.x - 1); x < xRange.y + 1; x += 1.0 / detail)
|
||||
for (double x = Math.Ceiling(xRange.x - 1); x < xRange.y + 1; x += 1.0 / _detail)
|
||||
{
|
||||
for (double y = Math.Ceiling(yRange.x - 1); y < yRange.y + 1; y += 1.0 / detail)
|
||||
for (double y = Math.Ceiling(yRange.x - 1); y < yRange.y + 1; y += 1.0 / _detail)
|
||||
{
|
||||
GetFromCache(step, x, y);
|
||||
}
|
||||
|
||||
@ -16,15 +16,12 @@ internal static class Program
|
||||
|
||||
GraphForm graph = new("One Of The Graphing Calculators Of All Time");
|
||||
|
||||
/*Equation equA = new(Math.Sin),
|
||||
Equation equA = new(Math.Sin),
|
||||
equB = new(Math.Cos);
|
||||
EquationDifference diff = new(2, equA, equB);
|
||||
ParametricEquation equC = new(0, 20, t => 0.0375 * t * Math.Cos(t), t => 0.0625 * t * Math.Sin(t) + 3);
|
||||
TangentLine tanA = new(2, 2, equA);
|
||||
graph.Graph(equA, equB, diff, equC, equB.ToColumnTable(-3, 3, 2), tanA);*/
|
||||
|
||||
SlopeField sf1 = new(1.5, (x, y) => Math.Cos(x) + Math.Sin(y));
|
||||
graph.Graph(sf1);
|
||||
graph.Graph(equA, equB, diff, equC, equB.ToColumnTable(-3, 3, 2), tanA);
|
||||
|
||||
Application.Run(graph);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user