This repository has been archived on 2022-08-05. You can view files and clone it, but cannot push or open issues or pull requests.
Lemonade/Lemonade/Fakku.cs

98 lines
4.5 KiB
C#

using System;
using System.Drawing;
using CC_Functions.Commandline.TUI;
namespace Lemonade
{
public static class EllipseDrawer
{
private static PointF GetEllipsePointFromX(float x, float a, float b) =>
//(x/a)^2 + (y/b)^2 = 1
//(y/b)^2 = 1 - (x/a)^2
//y/b = -sqrt(1 - (x/a)^2) --Neg root for upper portion of the plane
//y = b*-sqrt(1 - (x/a)^2)
new PointF(x, b * -(float)Math.Sqrt(1 - x * x / a / a));
public static void DrawEllipse(this Pixel[,] target, Rectangle area, Pixel basePixel)
{
int p0 = target.GetLength(0);
int p1 = target.GetLength(1);
bool[,] tmp = new bool[p0, p1];
DrawEllipse(tmp, new Rectangle(area.Y, area.X, area.Height, area.Width));
for (int i = 0; i < p0; i++)
for (int j = 0; j < p1; j++)
if (tmp[i, j])
target[i, j] = basePixel;
}
private static void DrawEllipse(bool[,] pixels, Rectangle area)
{
// Get the size of the matrix
int matrixWidth = pixels.GetLength(0);
int matrixHeight = pixels.GetLength(1);
int offsetY = area.Top;
int offsetX = area.Left;
// Figure out how big the ellipse is
float ellipseWidth = area.Width;
float ellipseHeight = area.Height;
// Figure out the radiuses of the ellipses
float radiusX = ellipseWidth / 2;
float radiusY = ellipseHeight / 2;
//Keep track of the previous y position
int prevY = 0;
bool firstRun = true;
// Loop through the points in the matrix
for (int x = 0; x <= radiusX; ++x)
{
int xPos = x + offsetX;
int rxPos = (int)ellipseWidth - x - 1 + offsetX;
if (xPos < 0 || rxPos < xPos || xPos >= matrixWidth) continue;
PointF pointOnEllipseBoundCorrespondingToXMatrixPosition = GetEllipsePointFromX(x - radiusX, radiusX, radiusY);
int y = (int) Math.Floor(pointOnEllipseBoundCorrespondingToXMatrixPosition.Y + (int)radiusY);
int yPos = y + offsetY;
int ryPos = (int)ellipseHeight - y - 1 + offsetY;
if (yPos >= 0)
{
if (xPos < matrixWidth && yPos < matrixHeight) pixels[xPos, yPos] = true;
if(xPos < matrixWidth && ryPos > -1 && ryPos < matrixHeight) pixels[xPos, ryPos] = true;
if (rxPos < matrixWidth)
{
if (yPos < matrixHeight) pixels[rxPos, yPos] = true;
if (ryPos > -1 && ryPos < matrixHeight) pixels[rxPos, ryPos] = true;
}
}
//While there's a >1 jump in y, fill in the gap (assumes that this is not the first time we've tracked y, x != 0)
for (int j = prevY - 1; !firstRun && j > y - 1 && y > 0; --j)
{
int jPos = j + offsetY;
int rjPos = (int)ellipseHeight - j - 1 + offsetY;
if(jPos == rjPos - 1) continue;
if(jPos > -1 && jPos < matrixHeight) pixels[xPos, jPos] = true;
if(rjPos > -1 && rjPos < matrixHeight) pixels[xPos, rjPos] = true;
if (rxPos < matrixWidth)
{
if(jPos > -1 && jPos < matrixHeight) pixels[rxPos, jPos] = true;
if(rjPos > -1 && rjPos < matrixHeight) pixels[rxPos, rjPos] = true;
}
}
firstRun = false;
prevY = y;
float countTarget = radiusY - y;
for (int count = 0; count < countTarget; ++count)
{
++yPos;
--ryPos;
// Set all four points in the matrix we just learned about
// also, make the indication that for the rest of this row, we need to fill the body of the ellipse
if(yPos > -1 && yPos < matrixHeight) pixels[xPos, yPos] = true;
if(ryPos > -1 && ryPos < matrixHeight) pixels[xPos, ryPos] = true;
if (rxPos < matrixWidth)
{
if(yPos > -1 && yPos < matrixHeight) pixels[rxPos, yPos] = true;
if(ryPos > -1 && ryPos < matrixHeight) pixels[rxPos, ryPos] = true;
}
}
}
}
}
}