/// <summary> /// Рисует прямую линию на канве /// </summary> /// <param name="canvas"></param> /// <param name="x1"></param> /// <param name="y1"></param> /// <param name="x2"></param> /// <param name="y2"></param> public override void Draw(StudCanvas canvas, ushort x1, ushort y1, ushort x2, ushort y2) { #region Подготовка параметров для вычисления _a = y1 - y2; _b = x2 - x1; _c = x1 * y2 - x2 * y1; DevTools.Normalize(ref x1, ref x2); DevTools.Normalize(ref y1, ref y2); DevTools.CheckRightX(ref x2, canvas); DevTools.CheckRightX(ref y2, canvas); #endregion for (float i = x1; i <= x2; i += XStep) { for (int j = y1; j <= y2; j++) { //На случай, если x2-x1 == 0 _currentY = j; if (CheckXY(i, j)) { if (_currentY > canvas.GetHeight()) continue; canvas.Field[(int)Math.Round(i), _currentY] = BackChar; } } } }
/// <summary> /// Рисует круг /// </summary> /// <param name="canvas"></param> /// <param name="x1"></param> /// <param name="y1"></param> /// <param name="x2"></param> /// <param name="y2"></param> public override void Draw(StudCanvas canvas, ushort x1, ushort y1, ushort x2, ushort y2) { #region Подготовка параметров для вычисления DevTools.Normalize(ref x1, ref x2); DevTools.Normalize(ref y1, ref y2); // Приводим прямоугольник к квадрату максимального размера, левый верхний угол остается на месте if ((x2 - x1) > (y2 - y1)) { x2 = Convert.ToUInt16(x1 + y2 - y1); } _radius = (double) (x2 - x1) / 2; _x0 = x1 + _radius; _y0 = y1 + _radius; DevTools.CheckRightX(ref x2, canvas); #endregion for (float i = x1; i <= x2; i += Step) { CheckY(i); if (IsSolid) { DevTools.CheckLowY(ref _currentY2, canvas); for (int j = _currentY1; j <= _currentY2; j++) { canvas.Field[(int)Math.Round(i), j] = BackChar; } } else { if (_currentY1 >= canvas.GetHeight()) continue; canvas.Field[(int) Math.Round(i), _currentY1] = BackChar; if (_currentY2 >= canvas.GetHeight()) continue; canvas.Field[(int) Math.Round(i), _currentY2] = BackChar; } } }
public void DrawWo(StudCanvas canvas, ushort x1, ushort y1, ushort x2, ushort y2) { DevTools.Normalize(ref x1, ref x2); DevTools.Normalize(ref y1, ref y2); int dx = x2 - x1; int dy = y2 - y1; double gradient = (double)dy / dx; // обработать начальную точку double xend = DevTools.Round(x1); double yend = y1 + gradient * (xend - x1); double xgap = 1 - DevTools.Fpart(x1 + 0.5); double xpxl1 = xend; // будет использоваться в основном цикле int ypxl1 = DevTools.Ipart(yend); DevTools.Plot(canvas, Convert.ToInt32(xpxl1), Convert.ToInt32(ypxl1), Convert.ToDouble(1 - DevTools.Fpart(yend) * xgap)); DevTools.Plot(canvas, Convert.ToInt32(xpxl1), Convert.ToInt32(ypxl1 + 1), Convert.ToDouble(DevTools.Fpart(yend) * xgap)); double intery = yend + gradient; // первое y-пересечение для цикла // обработать конечную точку xend = DevTools.Round(x2); yend = y2 + gradient * (xend - x2); xgap = DevTools.Fpart(x2 + 0.5); double xpxl2 = xend; // будет использоваться в основном цикле double ypxl2 = DevTools.Ipart(yend); DevTools.Plot(canvas, Convert.ToInt32(xpxl2), Convert.ToInt32(ypxl2), Convert.ToDouble(1 - DevTools.Fpart(yend) * xgap)); DevTools.Plot(canvas, Convert.ToInt32(xpxl2), Convert.ToInt32(ypxl2 + 1), Convert.ToDouble(DevTools.Fpart(yend) * xgap)); // основной цикл for (double i = xpxl1 + 1; i < xpxl2; i++) { DevTools.Plot(canvas, (int)i, DevTools.Ipart(intery), 1 - DevTools.Fpart(intery)); DevTools.Plot(canvas, (int)i, DevTools.Ipart(intery) + 1, DevTools.Fpart(intery)); intery = intery + gradient; } }
/// <summary> /// Вставляет одну канву в другую /// </summary> /// <param name="newCanvas">Ссылка на вставляемую канву</param> /// <param name="x1">Место вставки (левый верхний угол)</param> /// <param name="y1">Место вставки (левый верхний угол)</param> public void Paste(StudCanvas newCanvas, ushort x1, ushort y1) { ushort x2 = Convert.ToUInt16(newCanvas.Field.GetLength(0) - 1 + x1); ushort y2 = Convert.ToUInt16(newCanvas.Field.GetLength(1) - 1 + y1); if (x1 >= Field.GetLength(0) || y1 >= Field.GetLength(1)) return; DevTools.CheckRightX(ref x2, this); DevTools.CheckLowY(ref y2, this); for (int i = x1; i <= x2; i++) { for (int j = y1; j <= y2; j++) { Field[i, j] = newCanvas.Field[i - x1, j - y1]; } } }
//TODO: Обработать выход за границы канвы /// <summary> /// Рисует круг методом Брезенхейма /// </summary> /// <param name="canvas"></param> /// <param name="radius"></param> /// <param name="x0"></param> /// <param name="y0"></param> public void DrawBresenham(StudCanvas canvas, int radius, int x0, int y0) { int x = 0; int y = radius; int delta = 2 - 2 * radius; while (y >= 0) { canvas.Field[x0 + x, y0 + y] = BackChar; canvas.Field[x0 + x, y0 - y] = BackChar; canvas.Field[x0 - x, y0 + y] = BackChar; canvas.Field[x0 - x, y0 - y] = BackChar; int error = 2 * (delta + y) - 1; if (delta < 0 && error <= 0) { ++x; delta += 2 * x + 1; continue; } error = 2 * (delta - x) - 1; if (delta > 0 && error > 0) { --y; delta += 1 - 2 * y; continue; } ++x; delta += 2 * (x - y); --y; } }
public static void Plot(StudCanvas canvas, int x, int y, double br) { char[] backChars = { ',', '/', '%', '$', 'A' }; if (br < 0 || br >= 1) br = 0.99; canvas.Field[x, y] = backChars[(int) (br / .20f)]; }
/// <summary> /// Проверяет, не выходит ли данный х за правый край канвы. Если выходит - устанавливает его на предельно допустимое значение /// </summary> /// <param name="x">Проверяемое значение</param> /// <param name="canvas">Ссылка на канву</param> public static void CheckRightX(ref ushort x, StudCanvas canvas) { ushort width = Convert.ToUInt16(canvas.GetWidth() - 1); x = (x > width) ? width : x; }
/// <summary> /// Проверяет, не выходит ли данный y за нижний край канвы. Если выходит - устанавливает его на предельно допустимое значение /// </summary> /// <param name="y">Проверяемое значение</param> /// <param name="canvas">Ссылка на канву</param> public static void CheckLowY(ref ushort y, StudCanvas canvas) { ushort height = Convert.ToUInt16(canvas.GetHeight() - 1); y = (y > height) ? height : y; }
/// <summary> /// Проверяет, не выходит ли данный y за нижний край канвы. Если выходит - устанавливает его на предельно допустимое значение /// </summary> /// <param name="y">Проверяемое значение</param> /// <param name="canvas">Ссылка на канву</param> public static void CheckLowY(ref int y, StudCanvas canvas) { int height = canvas.GetHeight() - 1; y = (y > canvas.GetHeight()) ? height : y; }
static void Main(string[] args) { var rec = new StudRectangle(); var line = new StudLine(); var circle = new StudCircle(); #region Тест 1 (Прямоугольники) var canvas = new StudCanvas(15, 15); rec.IsSolid = false; rec.Draw(canvas, 8, 1, 1, 8); rec.IsSolid = true; rec.BackChar = '*'; rec.Draw(canvas, 3, 3, 6, 6); rec.BackChar = ' '; rec.Draw(canvas, 10, 10, 10, 3); rec.BackChar = 'S'; rec.Draw(canvas, 12, 12, 20, 20); rec.Draw(canvas, 4000, 3000, 2000, 1000); canvas.Draw("tests/1.txt"); #endregion #region Тест 2 (Линии) canvas = new StudCanvas(40, 40); line.IsSolid = true; line.Accuracy = 0.1f; line.Draw(canvas, 5, 5, 20, 15); line.IsSolid = false; line.Draw(canvas, 1, 1, 40, 4); line.Draw(canvas, 5, 10, 20, 20); line.Accuracy = 0.1f; line.Draw(canvas, 5, 21, 20, 15); line.BackChar = '@'; line.Draw(canvas, 1000, 1000, 2000, 2000); line.Draw(canvas, 20, 20, 50, 20); line.Draw(canvas, 20, 20, 20, 50); line.Draw(canvas, 15, 20, 16, 30); canvas.Draw("tests/2.txt"); #endregion #region Тест 3 (Круги) canvas = new StudCanvas(height: 50); circle.IsSolid = true; circle.Draw(canvas, 5, 5, 20, 15); circle.IsSolid = false; circle.Step = 1; circle.Draw(canvas, 1, 1, 40, 4); circle.Step = .1f; circle.Draw(canvas, 80, 30, 130, 80); circle.BackChar = '%'; circle.IsSolid = true; circle.Draw(canvas, 20, 40, 60, 5000); circle.Draw(canvas, 50000, 60000, 1000, 2000); circle.Step = .3f; circle.IsSolid = false; circle.Draw(canvas, 45, 15, 80, 50); circle.Step = .1f; circle.IsSolid = true; circle.Draw(canvas, 55, 25, 70, 40); canvas.Draw("tests/3.txt"); #endregion #region Тест 4 (Canvas.Mask && Canavs.Paste) canvas.Mask('%', 'U'); canvas.Mask('.', ' '); var canvas2 = new StudCanvas(10, 10); canvas.Paste(canvas2, 5, 5); canvas.Paste(canvas2, 95, 10); canvas.Paste(canvas2, 10, 45); canvas.Paste(canvas2, 1000, 4500); canvas.Draw("tests/4.txt"); #endregion #region Тест 5 (Смайлик) canvas = new StudCanvas(); circle.Draw(canvas, 5, 5, 95, 95); circle.IsSolid = false; circle.BackChar = '$'; circle.Step = .05f; circle.Draw(canvas, 4, 4, 96, 96); circle = new StudCircle(.5f, backChar: '*'); circle.Draw(canvas, 25, 25, 45, 45); circle.Draw(canvas, 55, 25, 75, 45); circle = new StudCircle(.1f, backChar: '%'); circle.Draw(canvas, 27, 35, 35, 45); circle.Draw(canvas, 57, 35, 65, 45); circle = new StudCircle(.1f, backChar: '@'); circle.Draw(canvas, 35, 50, 65, 80); canvas.Draw("tests/5.txt"); #endregion #region Тест 6 (Линии) canvas = new StudCanvas(); line = new StudLine(0.51f, false); line.Draw(canvas, 10, 10, 50, 50); line.Draw(canvas, 10, 50, 90, 70); canvas.Draw("tests/6.txt"); #endregion #region Тест 7 (Круги Брезенхейма) canvas = new StudCanvas(); circle = new StudCircle(); circle.DrawBresenham(canvas, 10, 30, 30); //Circle.DrawBresenham(Canvas, 50, 80, 80); canvas.Draw("tests/7.txt"); #endregion #region Тест 8 (Линия Ву) canvas = new StudCanvas(backChar: ' '); line = new StudLine(); line.DrawWo(canvas, 10, 10, 50, 50); line.DrawWo(canvas, 10, 50, 90, 70); line.DrawWo(canvas, 10, 50, 90, 63); canvas.Draw("tests/8.txt"); #endregion #region Тест 9 (Функция Plot) canvas = new StudCanvas(); DevTools.Plot(canvas, 5, 5, 0.27); DevTools.Plot(canvas, 5, 6, 0.12); DevTools.Plot(canvas, 5, 7, .57); DevTools.Plot(canvas, 5, 8, .81); canvas.Draw("tests/9.txt"); #endregion }