Repository navigation
Nerd_STF v3.1
Nerd_STF v3.1
Hi! It's been a while, but I've got a few things for you guys.
More color configurations.
I've been spending a lot of my time recently working on a Java library for FRC light strips and in the process I made a tool for gradients. I ended up finding myself wishing I had it in here, too, so I've added it.
It functions mostly as a list of colors and associated positions for those colors. You can add and remove colors over time, and you index it (or call .Get()) with a value between 0 and 1 to determine a color. For example:
Gradient<ColorRGB> gradient = new()
{
{ 0.0, ColorRGB.Red },
{ 0.5, ColorRGB.Green },
{ 1.0, ColorRGB.Blue },
};
Console.WriteLine(gradient[0.2].HexCode()); // #996600You can also quickly and easily visualize your gradients right in the console, so long as your console has compatibility for RGB colors.
Console.WriteLine("Our gradient: " + gradient.ToColorString());
produces this in the terminal:
![]()
Note that the resulting preview is actually a 1668 character string behind the scenes.
You can change the way the colors interpolate, if you'd like. Simply set gradient.Interpolation to any function that takes two colors and a float, and outputs a color.
Gradient<ColorRGB> gradient = new()
{
{ 0.0, ColorRGB.Red },
{ 0.5, ColorRGB.Green },
{ 1.0, ColorRGB.Blue },
};
// Interpolate through white. Don't look at the implementation too
// much, the point is to demonstrate that it can be set to whatever.
gradient.Interpolation = (a, b, t) =>
{
ColorRGB c;
if (t <= 0.5) (c, t) = (a, t * 2);
else (c, t) = (b, -2 * t + 2);
return (t, t, t) + c * (1 - t);
};
Console.WriteLine(" Through White: " + gradient.ToColorString() + "\n");
// Or you can set it to some simple templates.
gradient.Interpolation = Gradient<ColorRGB>.Nearest;
Console.WriteLine(" Nearest Neighbor: " + gradient.ToColorString() + "\n");
gradient.Interpolation = Gradient<ColorRGB>.Lerp;
Console.WriteLine("Default Interpolation: " + gradient.ToColorString() + "\n");ColorYCC
In addition, I have also implemented the YCbCr color space in the ColorYCC class. YCbCr is a way to convert RGB colors into a luminance value and two chrominance values. The conversion relies on the constants Kr, Kg, and Kb, which can be statically modified in the class. The constants are set to what I'm fairly certain is the most common standard, but the conversion system works for any
Validatable<T>
A small object I created mostly for the purposes of RGB <-> YCC conversion. It's done using matrix and vector multiplication, so I've cached the matrices required. However, if the K constants ever got changed, the matrix and its inverse needed to be recomputed. This is the purpose of the Validatable class.
When constructed, a method must be passed that "generates" a valid value when requested.
Validatable<int> obj = new(() -> ...);
Afterwards, when obj.Value is read, the object either runs the generation function and caches the result, or returns an already cached result.
To force the object to re-generate a value, simply declare it invalidated by obj.Invalidate(). This will cause the generator to be re-invoked only when required. It's essentially a re-usable version of System.Lazy<T>.
Discrete Math
I took discrete math last semester and decided to implement some of the things we discussed in that class here. Namely, the Nerd_STF.Mathematics.Discrete namespace contains mathematically-defined sets and relations. I think I went a little overboard with the abstraction here, I may use a better system in the future. But the important types to note are the DiscreteSet<T> and DiscreteRelation<T1, T2> types. The DiscreteSet contains a unique set of elements of type T, and a relation is a mapping of one set to another. Here's an example.
DiscreteSet<int> evens = [], odds = [], primes = [];
for (int i = 0; i < 20; i++)
{
if (i % 2 == 0) evens += i;
else odds += i;
if (IsPrime(i)) primes += i;
}
Console.WriteLine($"Evens set: {evens}\nOdds set: {odds}\nPrimes set: {primes}");
DiscreteRelation<int, int> relation = new();
foreach (int odd in odds)
{
if (odd == 1) continue;
foreach (int even in evens)
{
if (even % (odd - 1) == 0) relation += (even, odd);
}
}
Console.WriteLine("\nRelation between evens and odds:\n" + relation);Some things were handled better than others. The source code of the DiscreteRelation class specifically is a scuffed mess of long type names and abstraction, and none of this is particularly fast or efficient, but it works for simple situations and isn't too abstraction-heavy on the part of the user of this library.
Some final thoughts.
I may in the future condense DiscreteRelation<T1, T2> into a single type parameter for both the input and output. It makes things like the relation matrix and symmetry detection easier to implement.
I don't think I'm done with graphics. I've got some more ideas in the pipeline, but this library obviously takes a while to work on.
I also have a ton of very small tweaks I want to make. Things such as clamping color values in the constructors, or getting rid of SplitArray because the System.Linq namespace basically does that in a more modular way. Some small patches may be in order, but releasing this is such a pain I like to do it in bulk.
Take care, and enjoy 3.1!

