Made preload functions for most of the other graphables.
This commit is contained in:
parent
255a7d3774
commit
5c3cf9cafe
@ -46,17 +46,22 @@ public partial class PieChart : UserControl
|
||||
current += item.value;
|
||||
}
|
||||
|
||||
// Draw the outline.
|
||||
// Draw the outline of each slice.
|
||||
// Only done if there is more than one slice.
|
||||
if (Values.Count > 1)
|
||||
{
|
||||
Pen outlinePartsPen = new(Color.FromArgb(unchecked((int)0xFF_202020)), DpiFloat * 3 / 192);
|
||||
current = 0;
|
||||
foreach ((Color, double value) item in Values)
|
||||
{
|
||||
double start = 360 * current / sum,
|
||||
end = 360 * (current + item.value) / sum;
|
||||
if (item.value > 0)
|
||||
g.DrawPie(outlinePartsPen, rect, (float)start, (float)(end - start));
|
||||
|
||||
current += item.value;
|
||||
}
|
||||
}
|
||||
|
||||
// Outline
|
||||
Pen outlinePen = new(Color.FromArgb(unchecked((int)0xFF_202020)), DpiFloat * 5 / 192);
|
||||
|
||||
@ -466,12 +466,16 @@ public partial class GraphForm : Form
|
||||
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; //
|
||||
add.y *= 0.75; // Screen + 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);
|
||||
double step = ScreenSpaceToGraphSpace(new Int2(1, 0)).x
|
||||
- ScreenSpaceToGraphSpace(new Int2(0, 0)).x;
|
||||
step /= 10;
|
||||
|
||||
foreach (Graphable able in Graphables) able.Preload(xRange, yRange, step);
|
||||
Invalidate(false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -32,7 +32,7 @@ public abstract class Graphable
|
||||
|
||||
public abstract void EraseCache();
|
||||
public abstract long GetCacheBytes();
|
||||
public abstract void Preload(Float2 xRange, Float2 yRange);
|
||||
public abstract void Preload(Float2 xRange, Float2 yRange, double step);
|
||||
|
||||
public abstract bool ShouldSelectGraphable(in GraphForm graph, Float2 graphMousePos, double factor);
|
||||
public abstract Float2 GetSelectedPoint(in GraphForm graph, Float2 graphMousePos);
|
||||
|
||||
@ -52,5 +52,6 @@ public class ColumnTable : Graphable
|
||||
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) { }
|
||||
// Nothing to preload, everything is already cached.
|
||||
public override void Preload(Float2 xRange, Float2 yRange, double step) { }
|
||||
}
|
||||
|
||||
@ -116,9 +116,9 @@ public class Equation : Graphable
|
||||
return new(graphMousePos.x, GetFromCache(graphMousePos.x, 0.001));
|
||||
}
|
||||
|
||||
public override void Preload(Float2 xRange, Float2 yRange)
|
||||
public override void Preload(Float2 xRange, Float2 yRange, double step)
|
||||
{
|
||||
for (double x = xRange.x; x <= xRange.y; x += 1e-3) GetFromCache(x, 1e-4);
|
||||
for (double x = xRange.x; x <= xRange.y; x += step) GetFromCache(x, step);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -78,7 +78,16 @@ public class SlopeField : Graphable
|
||||
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 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 y = Math.Ceiling(yRange.x - 1); y < yRange.y + 1; y += 1.0 / detail)
|
||||
{
|
||||
GetFromCache(step, x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public delegate double SlopeFieldsDelegate(double x, double y);
|
||||
|
||||
@ -5,17 +5,32 @@ namespace Graphing.Graphables;
|
||||
|
||||
public class TangentLine : Graphable
|
||||
{
|
||||
public double Position { get; set; }
|
||||
public double Position
|
||||
{
|
||||
get => _position;
|
||||
set
|
||||
{
|
||||
currentSlope = DerivativeAtPoint(value);
|
||||
_position = value;
|
||||
}
|
||||
}
|
||||
private double _position;
|
||||
|
||||
protected readonly Equation parent;
|
||||
protected readonly EquationDelegate parentEqu;
|
||||
|
||||
protected readonly double length;
|
||||
|
||||
protected double currentSlope;
|
||||
|
||||
// No binary search for this, I want it to be exact.
|
||||
protected Dictionary<double, double> slopeCache;
|
||||
|
||||
public TangentLine(double length, double position, Equation parent)
|
||||
{
|
||||
Name = $"Tangent Line of {parent.Name}";
|
||||
|
||||
slopeCache = [];
|
||||
parentEqu = parent.GetDelegate();
|
||||
Position = position;
|
||||
this.length = length;
|
||||
@ -25,7 +40,7 @@ public class TangentLine : Graphable
|
||||
public override IEnumerable<IGraphPart> GetItemsToRender(in GraphForm graph)
|
||||
{
|
||||
Float2 point = new(Position, parentEqu(Position));
|
||||
return [MakeSlopeLine(point, DerivativeAtPoint(Position)),
|
||||
return [MakeSlopeLine(point, currentSlope),
|
||||
new GraphUiCircle(point, 8)];
|
||||
}
|
||||
protected GraphLine MakeSlopeLine(Float2 position, double slope)
|
||||
@ -40,17 +55,29 @@ public class TangentLine : Graphable
|
||||
}
|
||||
protected double DerivativeAtPoint(double x)
|
||||
{
|
||||
// If value is already computed, return it.
|
||||
if (slopeCache.TryGetValue(x, out double y)) return y;
|
||||
|
||||
const double step = 1e-3;
|
||||
return (parentEqu(x + step) - parentEqu(x)) / step;
|
||||
double result = (parentEqu(x + step) - parentEqu(x)) / step;
|
||||
slopeCache.Add(x, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public override Graphable DeepCopy() => new TangentLine(length, Position, parent);
|
||||
|
||||
public override void EraseCache() { }
|
||||
public override long GetCacheBytes() => 0;
|
||||
public override void EraseCache() => slopeCache.Clear();
|
||||
public override long GetCacheBytes() => slopeCache.Count * 16;
|
||||
|
||||
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 override void Preload(Float2 xRange, Float2 yRange, double step)
|
||||
{
|
||||
// Despite the tangent line barely using any data, when preloaded it
|
||||
// will always take as much memory as an equation. Seems like a bit much,
|
||||
// but may be used when the tangent line is moved. Not sure there's much
|
||||
// that can be changed.
|
||||
for (double x = xRange.x; x <= xRange.y; x += step) DerivativeAtPoint(x);
|
||||
}
|
||||
}
|
||||
|
||||
@ -14,10 +14,10 @@ internal static class Program
|
||||
|
||||
GraphForm graph = new("One Of The Graphing Calculators Of All Time");
|
||||
|
||||
Equation equ1 = new(x => -x * x + 2);
|
||||
Equation equ2 = new(x => x);
|
||||
Equation equ3 = new(x => -Math.Sqrt(x));
|
||||
graph.Graph(equ1, equ2, equ3);
|
||||
Equation possibleA = new(x => x * x * x);
|
||||
SlopeField sf = new(2, (x, y) => 3 * x * x);
|
||||
TangentLine tl = new(5, 2, possibleA);
|
||||
graph.Graph(possibleA, sf, tl);
|
||||
|
||||
// You can also now view and reset caches in the UI by going to
|
||||
// Misc > View Caches.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user