using Graphing.Forms; using Graphing.Parts; using System; using System.Collections.Generic; using System.Drawing; using System.Linq; namespace Graphing.Graphables; public class ColumnTable : Graphable { private static int tableNum; protected readonly Dictionary tableXY; protected readonly double width; public ColumnTable(double width, Dictionary tableXY) { tableNum++; Name = $"Column Table {tableNum}"; this.tableXY = tableXY; this.width = width; } public ColumnTable(double step, Equation equation, double min, double max) { Color = equation.Color; Name = $"Column Table for {equation.Name}"; tableXY = []; EquationDelegate equ = equation.GetDelegate(); width = 0.75 * step; double minRounded = Math.Round(min / step) * step, maxRounded = Math.Round(max / step) * step; for (double x = minRounded; x <= maxRounded; x += step) tableXY.Add(x, equ(x)); } public override long GetCacheBytes() => 16 * tableXY.Count; public override Graphable ShallowCopy() => new ColumnTable(width / 0.75, tableXY); public override IEnumerable GetItemsToRender(in GraphForm graph) { List items = []; foreach (KeyValuePair col in tableXY) { items.Add(GraphRectangle.FromSize(new Float2(col.Key, col.Value / 2), new Float2(width, col.Value), 0.625)); } return items; } public override bool ShouldSelectGraphable(in GraphForm graph, Float2 graphMousePos, double factor) { // Get closest value to mouse pos. double closestDist = double.PositiveInfinity, closestX = 0, closestY = 0; foreach (KeyValuePair points in tableXY) { double dist = Math.Abs(points.Key - graphMousePos.x); if (dist < closestDist) { closestDist = dist; closestX = points.Key; closestY = points.Value; } } Int2 screenMousePos = graph.GraphSpaceToScreenSpace(graphMousePos); Int2 minBox = graph.GraphSpaceToScreenSpace(new(closestX - width / 2, 0)), maxBox = graph.GraphSpaceToScreenSpace(new(closestX + width / 2, closestY)); int distX, distY; if (screenMousePos.x < minBox.x) distX = minBox.x - screenMousePos.x; // On left side. else if (screenMousePos.x > maxBox.x) distX = screenMousePos.x - maxBox.x; // On right side. else distX = 0; // Inside. if (closestY > 0) { if (screenMousePos.y > minBox.y) distY = screenMousePos.y - minBox.y; // Underneath. else if (screenMousePos.y < maxBox.y) distY = maxBox.y - screenMousePos.y; // Above. else distY = 0; // Inside. } else { if (screenMousePos.y < minBox.y) distY = minBox.y - screenMousePos.y; // Underneath. else if (screenMousePos.y > maxBox.y) distY = screenMousePos.y - maxBox.y; // Above. else distY = 0; // Inside. } int totalDist = (int)Math.Sqrt(distX * distX + distY * distY); return totalDist < 50 * factor * graph.ScalingFactor; } public override IEnumerable GetSelectionItemsToRender(in GraphForm graph, Float2 graphMousePos) { // Get closest value to mouse pos. double closestDist = double.PositiveInfinity, closestX = 0, closestY = 0; foreach (KeyValuePair points in tableXY) { double dist = Math.Abs(points.Key - graphMousePos.x); if (dist < closestDist) { closestDist = dist; closestX = points.Key; closestY = points.Value; } } Float2 textPoint = new(closestX, closestY); Int2 offset; ContentAlignment alignment; if (textPoint.y >= 0) { offset = new(0, -5); alignment = ContentAlignment.BottomCenter; } else { offset = new(0, 5); alignment = ContentAlignment.TopCenter; } return [ new GraphUiText($"{closestY:0.00}", textPoint, alignment, offsetPix: offset) ]; } // Nothing to preload, everything is already cached. public override void Preload(Float2 xRange, Float2 yRange, double step) { } }