From 255a7d3774983be0eec420e960c0992a722f64d5 Mon Sep 17 00:00:00 2001 From: That_One_Nerd Date: Sun, 17 Mar 2024 00:45:11 -0400 Subject: [PATCH] Starting progress on graph selection and preloading. More to come. --- Base/Forms/GraphForm.Designer.cs | 11 +++++- Base/Forms/GraphForm.cs | 57 +++++++++++++++++++++++++++++--- Base/Graphable.cs | 5 ++- Base/Graphables/ColumnTable.cs | 5 +++ Base/Graphables/Equation.cs | 24 ++++++++++++++ Base/Graphables/SlopeField.cs | 5 +++ Base/Graphables/TangentLine.cs | 5 +++ 7 files changed, 106 insertions(+), 6 deletions(-) diff --git a/Base/Forms/GraphForm.Designer.cs b/Base/Forms/GraphForm.Designer.cs index 15c0cfe..4bb2c83 100644 --- a/Base/Forms/GraphForm.Designer.cs +++ b/Base/Forms/GraphForm.Designer.cs @@ -41,6 +41,7 @@ MenuEquationsIntegral = new ToolStripMenuItem(); MenuMisc = new ToolStripMenuItem(); MenuMiscCaches = new ToolStripMenuItem(); + MiscMenuPreload = new ToolStripMenuItem(); GraphMenu.SuspendLayout(); SuspendLayout(); // @@ -129,7 +130,7 @@ // // MenuMisc // - MenuMisc.DropDownItems.AddRange(new ToolStripItem[] { MenuMiscCaches }); + MenuMisc.DropDownItems.AddRange(new ToolStripItem[] { MenuMiscCaches, MiscMenuPreload }); MenuMisc.Name = "MenuMisc"; MenuMisc.Size = new Size(83, 38); MenuMisc.Text = "Misc"; @@ -141,6 +142,13 @@ MenuMiscCaches.Text = "View Caches"; MenuMiscCaches.Click += MenuMiscCaches_Click; // + // MiscMenuPreload + // + MiscMenuPreload.Name = "MiscMenuPreload"; + MiscMenuPreload.Size = new Size(359, 44); + MiscMenuPreload.Text = "Preload Cache"; + MiscMenuPreload.Click += MiscMenuPreload_Click; + // // GraphForm // AutoScaleDimensions = new SizeF(13F, 32F); @@ -172,5 +180,6 @@ private ToolStripMenuItem MenuEquationsIntegral; private ToolStripMenuItem MenuMisc; private ToolStripMenuItem MenuMiscCaches; + private ToolStripMenuItem MiscMenuPreload; } } \ No newline at end of file diff --git a/Base/Forms/GraphForm.cs b/Base/Forms/GraphForm.cs index adf83a5..8523230 100644 --- a/Base/Forms/GraphForm.cs +++ b/Base/Forms/GraphForm.cs @@ -1,4 +1,5 @@ using Graphing.Graphables; +using Graphing.Parts; using System.Drawing.Drawing2D; namespace Graphing.Forms; @@ -200,6 +201,10 @@ public partial class GraphForm : Form PaintGrid(g); PaintUnits(g); + Point clientMousePos = PointToClient(Cursor.Position); + Float2 graphMousePos = ScreenSpaceToGraphSpace(new(clientMousePos.X, + clientMousePos.Y)); + // Draw the actual graphs. for (int i = 0; i < ables.Count; i++) { @@ -207,6 +212,18 @@ public partial class GraphForm : Form Brush graphBrush = new SolidBrush(ables[i].Color); Pen graphPen = new(graphBrush, DpiFloat * 3 / 192); foreach (IGraphPart gp in lines) gp.Render(this, g, graphPen); + + // Equation selection detection. + // This system lets you select multiple graphs, and that's cool by me. + if (ableDrag) + { + if (ables[i].ShouldSelectGraphable(this, graphMousePos, 2.5)) + { + Float2 selectedPoint = ables[i].GetSelectedPoint(this, graphMousePos); + GraphUiCircle select = new(selectedPoint, 8); + select.Render(this, g, graphPen); + } + } } base.OnPaint(e); @@ -227,11 +244,28 @@ public partial class GraphForm : Form private bool mouseDrag = false; private Int2 initialMouseLocation; private Float2 initialScreenCenter; + + private bool ableDrag = false; protected override void OnMouseDown(MouseEventArgs e) { - mouseDrag = true; - initialMouseLocation = new Int2(Cursor.Position.X, Cursor.Position.Y); - initialScreenCenter = ScreenCenter; + if (!mouseDrag) + { + Point clientMousePos = PointToClient(Cursor.Position); + Float2 graphMousePos = ScreenSpaceToGraphSpace(new(clientMousePos.X, + clientMousePos.Y)); + foreach (Graphable able in Graphables) + { + if (able.ShouldSelectGraphable(this, graphMousePos, 1)) ableDrag = true; + } + if (ableDrag) Invalidate(false); + } + + if (!ableDrag) + { + mouseDrag = true; + initialMouseLocation = new Int2(Cursor.Position.X, Cursor.Position.Y); + initialScreenCenter = ScreenCenter; + } } protected override void OnMouseUp(MouseEventArgs e) { @@ -242,9 +276,10 @@ public partial class GraphForm : Form Float2 graphDiff = new(pixelDiff.x * ZoomLevel / Dpi.x, pixelDiff.y * ZoomLevel / Dpi.y); ScreenCenter = new(initialScreenCenter.x + graphDiff.x, initialScreenCenter.y + graphDiff.y); - Invalidate(false); } mouseDrag = false; + ableDrag = false; + Invalidate(false); } protected override void OnMouseMove(MouseEventArgs e) { @@ -257,6 +292,7 @@ public partial class GraphForm : Form initialScreenCenter.y + graphDiff.y); Invalidate(false); } + else if (ableDrag) Invalidate(false); } protected override void OnMouseWheel(MouseEventArgs e) { @@ -425,4 +461,17 @@ public partial class GraphForm : Form cacheForm.TopMost = true; cacheForm.Show(); } + private void MiscMenuPreload_Click(object sender, EventArgs e) + { + Float2 min = MinVisibleGraph, max = MaxVisibleGraph; + Float2 add = new(max.x - min.x, max.y - min.y); + add.x *= 0.75; // Expansion + add.y *= 0.75; // + + Float2 xRange = new(min.x - add.x, max.x + add.x), + yRange = new(min.y - add.y, max.y + add.y); + + foreach (Graphable able in Graphables) able.Preload(xRange, yRange); + Invalidate(false); + } } diff --git a/Base/Graphable.cs b/Base/Graphable.cs index 5f42e15..6db3278 100644 --- a/Base/Graphable.cs +++ b/Base/Graphable.cs @@ -1,5 +1,4 @@ using Graphing.Forms; -using Graphing.Parts; namespace Graphing; @@ -33,4 +32,8 @@ public abstract class Graphable public abstract void EraseCache(); public abstract long GetCacheBytes(); + public abstract void Preload(Float2 xRange, Float2 yRange); + + public abstract bool ShouldSelectGraphable(in GraphForm graph, Float2 graphMousePos, double factor); + public abstract Float2 GetSelectedPoint(in GraphForm graph, Float2 graphMousePos); } diff --git a/Base/Graphables/ColumnTable.cs b/Base/Graphables/ColumnTable.cs index 876e070..567d07a 100644 --- a/Base/Graphables/ColumnTable.cs +++ b/Base/Graphables/ColumnTable.cs @@ -48,4 +48,9 @@ public class ColumnTable : Graphable return items; } + + public override bool ShouldSelectGraphable(in GraphForm graph, Float2 graphMousePos, double factor) => false; + public override Float2 GetSelectedPoint(in GraphForm graph, Float2 graphMousePos) => default; + + public override void Preload(Float2 xRange, Float2 yRange) { } } diff --git a/Base/Graphables/Equation.cs b/Base/Graphables/Equation.cs index fb265e8..9cd34be 100644 --- a/Base/Graphables/Equation.cs +++ b/Base/Graphables/Equation.cs @@ -96,6 +96,30 @@ public class Equation : Graphable public override Graphable DeepCopy() => new Equation(equ); public override long GetCacheBytes() => cache.Count * 16; + + public override bool ShouldSelectGraphable(in GraphForm graph, Float2 graphMousePos, double factor) + { + Int2 screenMousePos = graph.GraphSpaceToScreenSpace(graphMousePos); + + (_, _, int index) = NearestCachedPoint(graphMousePos.x); + Int2 screenCachePos = graph.GraphSpaceToScreenSpace(cache[index]); + + double allowedDist = factor * graph.DpiFloat * 80 / 192; + + Int2 dist = new(screenCachePos.x - screenMousePos.x, + screenCachePos.y - screenMousePos.y); + double totalDist = Math.Sqrt(dist.x * dist.x + dist.y * dist.y); + return totalDist <= allowedDist; + } + public override Float2 GetSelectedPoint(in GraphForm graph, Float2 graphMousePos) + { + return new(graphMousePos.x, GetFromCache(graphMousePos.x, 0.001)); + } + + public override void Preload(Float2 xRange, Float2 yRange) + { + for (double x = xRange.x; x <= xRange.y; x += 1e-3) GetFromCache(x, 1e-4); + } } public delegate double EquationDelegate(double x); diff --git a/Base/Graphables/SlopeField.cs b/Base/Graphables/SlopeField.cs index 9fd63dc..a26200f 100644 --- a/Base/Graphables/SlopeField.cs +++ b/Base/Graphables/SlopeField.cs @@ -74,6 +74,11 @@ public class SlopeField : Graphable public override void EraseCache() => cache.Clear(); public override long GetCacheBytes() => cache.Count * 48; + + public override bool ShouldSelectGraphable(in GraphForm graph, Float2 graphMousePos, double factor) => false; + public override Float2 GetSelectedPoint(in GraphForm graph, Float2 graphMousePos) => default; + + public override void Preload(Float2 xRange, Float2 yRange) { } } public delegate double SlopeFieldsDelegate(double x, double y); diff --git a/Base/Graphables/TangentLine.cs b/Base/Graphables/TangentLine.cs index 33ceb7f..aa4596f 100644 --- a/Base/Graphables/TangentLine.cs +++ b/Base/Graphables/TangentLine.cs @@ -48,4 +48,9 @@ public class TangentLine : Graphable public override void EraseCache() { } public override long GetCacheBytes() => 0; + + public override bool ShouldSelectGraphable(in GraphForm graph, Float2 graphMousePos, double factor) => false; + public override Float2 GetSelectedPoint(in GraphForm graph, Float2 graphMousePos) => default; + + public override void Preload(Float2 xRange, Float2 yRange) { } }