Releases: That-One-Nerd/Graphing
Graphing 1.3.0
Here's another graphing calculator update. I know it's been a while, sorry about that. There have been a lot of new features and improvements. Here's what's new:
Of course, there are some new graphables! There's a small one, the EquationDifference
graphable. This one is made to display the difference between two given equations. Nothing huge. There's also the ParametricEquation
graphable, which is self explanatory. It lets you graph parametric equations. The code right now is not particularly optimized, but that's alright for now. It takes in a range for t
, and two delegate methods, one for x
with time and one for y
with time.
I've replaced the original system for some UI elements. Things like the integrating and deriving buttons would require the graphable to be an equation specifically. That kind of limits things and prevents it from being as homebrew-able as possible. So that's been replaced. I've instead added interfaces for each of this things. So if you want your graphable to be able to be integrated, just implement the IIntegrable
interface. Same for the IDerivable
interface. There are also now more UI options. Converting an equation to its slope field is possible, and there's an interface for that: IConvertSlopeField
, as well as some others: IConvertEquation
and IConvertColumnTable
. Each of those conversion interfaces come with a boolean like UngraphWhenConvertedTo[...]
which specify whether the original graphable should remain graphed once converted. So like when you convert an equation to its slope field, you probably still want the equation there. But if you wanted to convert an equation difference to an equation itself, you probably don't want the original line.
We're almost done with interfaces. One more UI element that's been added is the ability to shift a graphable along the X and Y axes in the UI. It's under the "Operations" tab, and it can be controlled again with interfaces. You don't need to implement functionality for both the X and Y axes at the same time if your graphable doesn't support that (for example, a tangent line). You can instead just implement the X and Y interfaces. For X, implement the ITranslatableX
, ITranslatableY
for Y, and ITranslatableXY
as a shorthand for both.
Speaking of UI elements, there are some new ones. Slope fields can now have their detail modified outside of the code. It's under the "Elements > Detail" tab. This one has no interface; you must be a slope field to be added to that list. This one is a bit too specific to abstract away, though there comes another graphable that can have its detail modified in some way, it'll also probably be added to that tab, only it'll invoke a different UI form. There's also the zoom form. This one already existed for a bit but has been completely revamped. The graph now supports non-square zoom levels, so things like a box zoom have been added. There's also the "Match Aspect" button, which stretches the graph window to make the zoom square. Then there's "Normalize," which zooms in/out until one of the axes is set to the default zoom. And lastly there's the ability to reset the zoom, which also resets the window zoom level. If you want to modify the exact endpoints for the window, that's also an option, and you can lock the viewport to prevent dragging, scaling, or resetting. A lot of talk for "I made the zoom system better."
There's also an update checker now! It doesn't do much at the moment, it's pretty limited as this package is just a library. I don't have the ability to replace the graphing DLL while the application is running, and then I'd have to recompile and breaking changes could screw that up. So it is just a simple popup on the bottom right of the graph form that takes you to the GitHub release if you click it. You won't be able to see it until the next release, obviously, but it's there.
One more big thing. The graphable selection system has changed. This is a fairly breaking change but not something difficult to adapt. Rather than returning a specific selected point when asked, you return a collection of more graph parts. So for example, you can have custom selection text messages (like displaying the slope rather than the point coordinates) or have additional UI elements if need be.
Anyway, that's all for now. I don't think I missed anything here? Again, sorry for the wait, see you in 1.4!
And here's the exact changelog, as usual.
- Added an
.Abstract
namespace with the following interfaces:IConvertColumnTable
: Allows the graphable to convert to a column table. Appears in the UI under "Convert > Column Table"IConvertEquation
: Allows the graphable to convert to an equation. Appears in the UI under "Convert > Equation"IConvertSlopeField
: Allows the graphable to convert to a slope field. Appears in the UI under "Convert > Slope Field"ITranslatable
: Marks the graphable as shiftable. Does nothing on its own.ITranslatableX
: Marks the graphable as shiftable along the X-axis. Appears in the UI under "Operations > Translate"ITranslatableY
: Marks the graphable as shiftable along the Y-axis. Appears in the UI under "Operations > Translate"ITranslatableXY
: A shorthand for implementing bothITranslatableX
andITranslatableY
. Both shifting UIs are accessed in the same place.
- Added the following static readonly color properties to the
GraphForm
:BackgroundColor
: Controls the background color of the form. Currently pure white.ZoomBoxColor
: Controls the color of the zoom-box rectangle. Currently pure black.MajorUpdateColor
: Controls the text color of the update popup when the latest release is a major release above of the current version. Currently set to a red tone (#F74434).MajorUpdateColor
: Controls the text color of the update popup when the latest release is only a minor release above of the current version. Currently set to a orangish-gold tone (#FCA103).
- Made the zooming system allow for rectangular zooming. The X and Y zoom levels can be changed independently.
- Got rid of the segment check in the zooming mechanism since the zoom box mechanism can break it a bit.
- Changed the icon of the reset viewport button.
- Added a property called
ViewportLocked
that prevents the viewport from being moved, resized, or reset. Locking the viewport makes the reset viewport button use a padlock symbol. - Added a callback in
GraphForm
for when the viewport is zoomed in or out. - Added an update checker. Runs in an asyncronous task so as to not lag startup on a poor connection.
- Replaced the default text on selection with a more customizable method.
- Replaced the selection system with a small state machine to control the various click-drag functions.
- Added the ability to set the zoom of the graph form by drawing a box.
- Added the ability to ungraph a graphable from the form.
- Added a method to determine if a point on the graph is visible to the user.
- The graph form now stores a reference to the current zoom form when opened to prevent duplicates.
- Zooming in with the scroll wheel now focuses the zooming around the cursor's currently selected point.
- Pressing the reset button now does a full reset instead of a previous partial one.
- Added the ability to change a slope field's detail in the UI. Found under "Elements > Detail"
- Reworked most of the original UI elements to hopefully be more extendable.
- Added some more options. See above with the interfaces, those are most of them.
- The zoom form now tries to appear to the right of the graph form (though if it goes off the screen it won't do that).
- Added a public method to do a full reset of the viewport (
ResetAllViewport()
). - The graph form now stores a reference to the current cache form when opened to prevent duplicates.
- Made a bunch of
object sender
s nullable. Gotta be conventionally correct! - The zoom form has been completely reworked. Now it's a lot more customizable.
- The cache form now ignores graphables with zero cache. Doesn't change much.
- Replaced the method in the abstract
Graphable
class namedDeepCopy()
with one calledShallowCopy()
since I wasn't actually doing any deep copying in my implementations of it. - The column table no longer does any deep copying. This was I think the one place I actually used deep-copied internal variables.
- Added new selection code for the
ColumnTable
. - Implemented a bunch of the earlier abstract interfaces in the
Equation
graphable (specificallyITranslatableXY
, andIConvertSlopeField
). - Added a callback for when the equation is rendered. I don't use it much and I'll probably get rid of it, having callbacks in graphables is not recommended.
- Added the ability for an equation to convert to its slope field.
- Added the ability for an equation to convert to a column table.
- Added a public method in the
Equation
graphable for getting an exact value from it. - Slightly reworked the selection text in the
Equation
graphable. - Added a graphable that displays the difference between two equations, called the
EquationDifference
. It can convert to an equation that displays the difference overx
and can be translated. - Slightly reworked the selection text in the
IntegralEquation
graphable. - Added a
ParametricEquation
graphable. It takes in two delegates, one forx
over time and one fory
. - Made the detail in the
SlopeField
graphable a public property that can be modified. Also made it adouble
instead of anint
. Reworked the renderer a bit so decimal slope fields work well. - Improved the
SlopeField
selection UI items to show the slope rather than the coordinates. - Made the
TangentLine
graphable implement the interfacesIConvertEquation
andITranslatableX
. - Made the cache of the
TangentLine
clear when the parent is modified. The only use of a grap...
Graphing 1.2.0
Graphing 1.2.0
This is the third important release of the graphing calculator. This update is
fairly all over the place, but here are the important parts. First of all, the
system for integrating equations has been drastically improved. Originally, the
system was laggy for intensive equations and especially for second or third
order integrals, and the line itself would appear quite choppy if you zoom in
far enough. This was because the original system would compute the integral at
a point by just accumulating the area from 0 to that point. So if you asked for
the integral of an equation at 2.1 and then again at 2.2, the work for
calculating 2.1 would be done twice.
This has since been improved. There is a new graphable specifically for the
displaying integrals called the IntegralEquation
. This graphable is a
modified version of the Equation
graphable with some notable optimizations.
Now, rather than doing duplicate work when calculating points one-after-another
is done by increasing an internal stepper rather than recomputing from scratch.
The result makes integrating many points in order (which is done for hundreds
of points per frame) is now remarkably faster. High order integrals are now
almost as fast as their parent equation, and in this regard only, I think I
have a win against Desmos. Their integration can prove to be slower than mine.
Another benefit of this new method is that the change in the accumulation is
dependent on zoom, meaning the graph does not appear jagged or choppy at all
when you zoom in. It has a side of effect of making the graph more laggy when
you zoon in a whole bunch, but for most purposes, this system is much faster.
I've also made the line thickness of the graph dependent on the DPI of the
monitor used. I honestly would've thought that Windows Forms would handle that
part for me, but it doesn't. So in the GraphForm
there is now a new property
called DpiFloat
which represents the DPI of the screen. All the graph parts
now have their line thickness scaled by a factor of DpiFloat / 192
, since my
development display has a DPI of 192, I'm using that for reference. It's a bit
redundant though. I think in a future update (marked on the project board),
I'll replace the DpiFloat / 192
system with a simpler DpiFactor
property.
And I've made some light progress on a more modular approach to applying
operators to graphs. Currently you can only integrate and derive in the UI,
but I've replaced the simple check for an Equation
type with a more modular
interface check. To make your graphable appear in the derivation menu, make
your graphable implement the IDerivable
interface.
That's about it for now. If you want the specific changelog, it's below:
- Added
.github/
to the Gitignore. Not sure why it's appeared but I'm adding it just in case. - Added the following feature interfaces:
IDerivable
- Used to derive graphs.IIntegrable
- Used to integrate graphs.
- Disabled implicit usings in the project properties. It's mostly for debugging help.
- Added some more NuGet tags.
- Added the
DpiFloat
property to theGraphForm
for use with scaling UI elements.- Also added the
DpiFloat
property to thePieChart
control for the same purpose.
- Also added the
- The
PieChart
control no longer draws an extraneous edge when there's only one item on the chart. - Increased the maximum zoom level from
0.01
to0.00001
. - The form now draws units on the main axes which scale with zoom level.
- There is now a
UnitsTextColor
constant for the text color.
- There is now a
- Created a graph selection detection system for specific graphables.
- Stores generated pens to prevent duplicate work.
- Prevents scrolling the screen when selecting a graph.
- The color picker form now won't appear partially or entirely off the edge of the screen.
- Replaced generating UI options for equations with generating UI options for individual interfaces.
- Currently
IDerivable
andIIntegrable
.
- Currently
- Replaced the old
EquationComputeDerivative_Click
method with a simplerGraph(derivable.Derive())
method. - Replaced the old
EquationComputeIntegral_Click
method with a simplerGraph(integrable.Integrate())
method. - The cache form now won't appear partially or entirely off the edge of the screen.
- The cache form now is always shown on top of the main form.
- Added the ability to preload graphables at a higher depth.
- Made the buttons for the cache viewer variables and made them scale with DPI.
- Got rid of the very slight transparency in preset graph colors.
- Made all optional methods
virtual
instead ofabstract
. - Added the following optional methods to the base
Graphable
type:void Preload(Float2, Float2, double)
bool ShouldSelectGraphable(in GraphForm, Float2, double)
Float2 GetSelectedPoint(in GraphForm, Float2)
- Removed the unused
EraseCache
method inColumnTable
- Made the
Equation
graphable implementIDerivable
andIIntegrable
. - The equation sampling rate now scales with DPI.
- Added the ability to select a point along an equation.
- The equation now draws the extra little bit that was previously missing on the right side of the screen.
- Added the
IntegralEquation
, which can integrate equations much faster than the standard method. - Added the ability to select a point along a
SlopeField
. - Made the
Position
property of aTangentLine
more dynamic. - Added the ability to cache previous heights and slopes in a
TangentLine
automatically. - In
TangentLine
, made theMakeSlopeLine
use already-existing properties rather than arguments. - Added a caching system to
DerivativeAtPoint
inTangentLine
. - Added implementations to
EraseCache
andGetCacheBytes
inTangentLine
. - Added the ability to select a point along a tangent line.
- Replaced the
Render
method passing aBrush
with one passing aPen
to prevent duplicate work. - Modified the README some.
- Changed the demonstration default.
Graphing 1.1.0
Graphing 1.1.0
This is the second release of the graphing calculator. This update focuses more
on the optimization of general equations in the engine. The main improvement is
that the original computing method would do a whole lot of duplicate work if
you moved the viewport. We've already calculate the value of the equation at a
given point, we shouldn't have to do that again.
So in this update, a caching system has been implemented. It is most targeted
to the Equation
graphable, but also partially applies to the SlopeField
graphable. Values generated during rendering are cached by the graphable to be
reclaimed faster in future calls for a value at a given point. The caches get
fairly big but not huge. In all my testing, the cache rarely got above 2 MB.
The total cache depends of course on the amount of equations being graphed, but
assuming it remains at a reasonable level, the memory usage will certainly stay
in the single-digit megabyte range.
The cached data can be visualized in the UI by using the toolbar. Go to Misc >
View Caches to see the caches. A window will open up displaying a pie chart of
the memory usage and the ability to reset a given equation's cache. Note that
resetting a cache does not guarantee it will go entirely to zero, as some data
is required for the first-time render. But it will certainly shrink to just a
few kilobytes.
It's a medium-sized tweak, but I'm proud of it. In addition, I've also added
the some more graphables, including a tangent line of a equation at a point
(use the TangentLine
graphable) and a simple bar graph (use the ColumnTable
graphable). I guess I've never specified directly, but you can script this
calculator. You can write your own graphables simply by deriving from the
abstract Graphable
type and implementing the required methods. I may make a
wiki detailing how to write your own graphables in the future.
The other decent change is to add the ability to draw more than just lines.
Rather than a graphable generating just a collection of GraphLine
s, it now
generates a collection of IGraphPart
s, where GraphLine
derives from. In
addition to a line now, a GraphUICircle
exists, which draws a
constant-pixel-size circle at a position in graph space, and a
GraphRectangle
, which draws a rectangle in graph space. The UI circle is used
in the tangent line graphable and the rectangle in the column table
respectively. More graph parts can be scripted as well, just by deriving from
the IGraphPart
interface.
Anyway, that's the big stuff. Here's a more detailed list of every change:
- Added the ability to format a number in terms of file size (eg. "1024" → "1.00 KB")
- Added a form control that draws a pie chart given some values and colors.
- Made the base graph colors (axis colors, semi-axis colors, etc.) static constants at the top of the file.
- Enabled anti-aliasing in the graph.
- Replaced the built-in line rendering scheme with a more generalized part rendering scheme.
- Moved the code that renders lines from
GraphForm:157-167
toGraphLine:23-30
- Moved the code that renders lines from
- Started using
double.IsFinite
as opposed todouble.IsNormal
, because apparently zero is not normal. - The
GraphForm.Graph
method now accepts a collection of items to graph rather than just one. - Prevented some extra casting when regenerating menu items.
- Changed the integral step from
0.1
to0.01
. - Added a button in the UI that opens a form to view graph caches.
- Replaced namespace with a file-scoped namespace in
SetZoomForm
- Added a form to view graph caches.
- Replaced the return type of the abstract
GetItemsToRender
from anIEnumerable<Line2d>
to anIEnumerable<GraphLine>
. - Added the following abstract methods in
Graphable
Graphable DeepCopy()
void EraseCache()
long GetCacheBytes()
- Added the
ColumnTable
graphable which represents a bar graph. - Added a
List<Float2>
cache in theEquation
graphable. - Rather than calling the delegate directly, the
Equation
attempts to load its cached value first. - Renamed
Line2d
toGraphLine
- Added a
List<Float2>
cache in theEquation
graphable. - Added a
TangentLine
graphable which represents a tangent of an equation at one point. - Added the
IGraphPart
interface. - Added a rectangle graph part (
GraphRectangle
). - Added a UI circle graph part (
GraphUICircle
).
Graphing 1.0.0
This is the initial version. Fairly simple but it all works.