C# Графика(прямая линия и круг)

469
24 февраля 2018, 19:08

Можно ли в консоли нарисовать прямую линию и круг?(не в форме, где нужно добавлять специальный блок, где можно рисовать) Если да, тогда хотелось бы увидеть короткий пример. Так как не могу ничего найти в поисковике или других ресурсов!

Answer 1

Ответ на этот вопрос пересекается с другим моим ответом, настоятельно рекомендую прочитать и его тоже.

Посмотрите на консольный вывод немного под другим углом и увидите наличие всех графических возможностей, за исключением готовых библиотек. Картинка состоит из пикселей, сейчас они почти квадратные (но так было не всегда, привет от ДВК и прочих "динозавров" с растровым дисплеем). Что может заменить пиксели в консоли? Правильно, символы. Да придется установить шрифт "по-квадратнее", что-то вроде точечного шрифта 8х9 или использовать пары символов шрифта 5х12,или просто смириться с тем, что пиксели у вас прямоугольные.

Далее есть варианты:

  1. ASCII-графика. Можно нагуглить огромное количество изображений выполненных в данной технике. В период дисплеев на основе знакогенератора, это был единственно возможный вариант представления графической информации. Ключевая особенность - для формирования изображения и передачи цвета используются алфавитно-цифровые знаки. C# использует юникод - поэтому выбор печатных знаков огромен.

  2. Табличная графика, или псевдографика. Это особый набор символов, созданный для оформления таблиц. Тут в общем-то ничего особо интересного пожалуй нет, но если нужны таблицы, прямоугольники, вертикальные и горизонтальные линии что-то лучше придумать тоже довольно сложно.

  3. Особая версия пиксель-арта в ультра-низком разрешении (по умолчанию 80х25, настраивается) и ограничением в 16 цветов. Количество оттенков цвета можно увеличить в несколько раз, если использовать для вывода особые символы в сочетании с цветом фона, например как в ответе по ссылке в комментарии @A K.

Выбор стиля естественно за вами.

Так как готовых библиотек нет, примитивы вроде линий и окружностей придется рисовать самостоятельно. Из доступного у нас есть только рисование точки (с помощью вывода символа разумеется). Рисование вертикальных и горизонтальных линий не составляет проблем. Просто смещаем курсор по одной координате и рисуем очередной символ-пиксель.

С кривыми или наклонными прямыми придется вспоминать математику. Выглядеть будет как-то так:

Точки линии сначала вычисляются, для этого понадобится знать формулу кривой или вывести ее из начальных параметров (точки начала и конца для линий, координаты центра и радиус для окружности и т.д.). Так как не все значения будут целыми, а координаты даже обычных пикселей строго целые, придется вычислить масштабные коэффициенты и привести исходные дробные значения к целым в соответствующем масштабе. После, по полученному массиву точек в целых координатах выводим символы пиксели в консоль.

Ну и небольшой пример для демонстрации. Возьмем самый простой примитив - наклонную линию, чтобы показать общий принцип и, при этом, не уходить глубоко в математику.

Исходные данные:
дефолтный размер экрана консоли - 80х25 знаков;
рисовать будем диагональную линию из нижнего левого угла в правый верхний; координаты начала линии - double x1 = 0, y1 = 24;
координаты конца линии - double x2 = 79, y2 = 0;
знак пикселя - '*'

Прямую можно задать коэффициентом смещения по x при единичном смещении по y или наоборот.

double dx = x2 - x1;//79 - 0 = 79
double dy = y2 - y1;//0 - 24 = -24

Теперь нормализуем смещения к единице, для этого разделим полученные значения на модуль наибольшего из них.

double maxDelta = Math.Abs(Math.Max(dx, dy));
dx = dx / maxDelta;
dy = dy / maxDelta;

Считаем масштабный коэффициент, чтобы вся линия уместилась на видимой части консоли.

double xScale = (Math.Max(x1, x2) > (Console.WindowWidth - 1)) 
                    ? Math.Max(x1, x2) / (Console.WindowWidth - 1) 
                    : 1;
double yScale = (Math.Max(y1, y2) > (Console.WindowHeight - 1)) 
                    ? Math.Max(y1, y2) / (Console.WindowHeight - 1) 
                    : 1;
double scale = Math.Max(xScale, yScale);

Теперь можно рисовать линию.

//настоящие координаты точек линии
double x = x1;
double y = y1;
//целые координаты пикселей для точек линии
int graphX = (int)Math.Round(x / scale);
int graphY = (int)Math.Round(y / scale);
while(graphX >= 0 && graphX < Console.WindowWidth 
    && graphY >= 0 && graphY < Console.WindowHeight)
{
    Console.SetCursorPosition(graphX, graphY);
    Console.Write('*');
    x += dx;
    y += dy;
    graphX = (int)Math.Round(x / scale);
    graphY = (int)Math.Round(y / scale);
}

И получаем вот такую картинку:

Как видите, техника древняя и довольно простая. Применяется не только в консольной графике, но и в обычной, при по-пиксельном рисовании. Все остальные примитивы обрабатываются похожим образом, либо с предварительным полным расчетом точек линии в массиве для сложных кривых. С окружностью и эллипсом придется вспомнить или подучить базовую тригонометрию, а именно синусы и косинусы.

READ ALSO
Ожидание загрузки диалогового окна

Ожидание загрузки диалогового окна

На сайте с помощью selenium chrome нажимаю в браузере на кнопку добавить файлы, открывается диалоговое окно, но на разных компьютерах оно открывается...

259
Удалить из файла первую строку со смещением

Удалить из файла первую строку со смещением

Как удалить первую строку в файле со смещением? То есть чтобы не осталось пустой строки, чтобы она вообще исчезла

197
Как получить HMID видеокарты из реестра?

Как получить HMID видеокарты из реестра?

Как на C# получить HMID видеокарты из реестра Windows?

224
Как прослушивать используемый com-port?

Как прослушивать используемый com-port?

Есть десктопная программа, которая отправляет команды устройству, подключенному через com-portЕсть ли в с# возможность сниффить траффик от софта...

213