/// <summary>
/// Processes an area and applies a gradient calculation to each part of the area.
/// </summary>
/// <param name="position">The center of the gradient.</param>
/// <param name="strength">The width of the gradient spread.</param>
/// <param name="angle">The angle to apply the gradient.</param>
/// <param name="area">The area to calculate.</param>
/// <param name="applyAction">The callback called for each part of the area.</param>
public static void GradientFill(Point cellSize, Point position, int strength, int angle, Rectangle area, ColorGradient gradient, Action <int, int, Color> applyAction)
{
double radians = angle * Math.PI / 180; // = Math.Atan2(x1 - x2, y1 - y2);
Vector2 angleVector = new Vector2((float)(Math.Sin(radians) * strength), (float)(Math.Cos(radians) * strength)) / 2;
Vector2 location = new Vector2(position.X, position.Y);
if (cellSize.X > cellSize.Y)
{
angleVector.Y *= cellSize.X / cellSize.Y;
}
else if (cellSize.X < cellSize.Y)
{
angleVector.X *= cellSize.Y / cellSize.X;
}
Vector2 endingPoint = location + angleVector;
Vector2 startingPoint = location - angleVector;
double x1 = (startingPoint.X / (double)area.Width) * 2.0f - 1.0f;
double y1 = (startingPoint.Y / (double)area.Height) * 2.0f - 1.0f;
double x2 = (endingPoint.X / (double)area.Width) * 2.0f - 1.0f;
double y2 = (endingPoint.Y / (double)area.Height) * 2.0f - 1.0f;
double start = x1 * angleVector.X + y1 * angleVector.Y;
double end = x2 * angleVector.X + y2 * angleVector.Y;
for (int x = area.Left; x < area.Width; x++)
{
for (int y = area.Top; y < area.Height; y++)
{
// but we need vectors from (-1, -1) to (1, 1)
// instead of pixels from (0, 0) to (width, height)
double u = (x / (double)area.Width) * 2.0f - 1.0f;
double v = (y / (double)area.Height) * 2.0f - 1.0f;
double here = u * angleVector.X + v * angleVector.Y;
double lerp = (start - here) / (start - end);
//lerp = Math.Abs((lerp - (int)lerp));
lerp = MyMathHelper.Clamp((float)lerp, 0f, 1.0f);
int counter;
for (counter = 0; counter < gradient.Stops.Length && gradient.Stops[counter].Stop < (float)lerp; counter++)
{
;
}
counter--;
counter = (int)MyMathHelper.Clamp(counter, 0, gradient.Stops.Length - 2);
float newLerp = (gradient.Stops[counter].Stop - (float)lerp) / (gradient.Stops[counter].Stop - gradient.Stops[counter + 1].Stop);
applyAction(x, y, ColorHelper.Lerp(gradient.Stops[counter].Color, gradient.Stops[counter + 1].Color, newLerp));
}
}
}