Звезда
Звезду можно получить из правильного многоугольника если каждую вторую точку рисовать с другим (внутренним) радиусом. Воспользуемся кодом с предыдущего урока и слегка модифицируем его
private void Form1_Paint(object? sender, PaintEventArgs e)
{
var gr = e.Graphics;
gr.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
gr.Clear(Color.Black);
PointF? prevPoint = null;
double radius1 = 160; // внешний радиус звезды
double radius2 = 60; // внутренний радиус звезды
var centerX = ClientRectangle.Width / 2;
var centerY = ClientRectangle.Height / 2;
int n = 5; // количество лучей у звезды
var step = 360.0f / (n * 2); // шаг градусов
bool even = false; // флаг указывающий какой из радиусов использовать на текущем шагу
for (int i = 0; i <= n * 2; i++) // пробегаемся циклом по всем иднексам вершин звезды
{
float ang = i * step; // получаем из индекса угол путем домнажения на шаг step
var radians = ang * Math.PI / 180.0 - Math.PI / 2; // переводим в радианы и поворачиваем на -90°
even = !even; // переключаем радиус
var radius = even ? radius1 : radius2; // выбираем радиус исходя из текущего состояния флага even
// расчитываем координаты точки (x, y)
var x = centerX + radius * Math.Cos(radians);
var y = centerY + radius * Math.Sin(radians);
PointF point = new PointF((float)x, (float)y);
if (prevPoint != null)
gr.DrawLine(Pens.White, prevPoint.Value, point); // рисуем линию между точками
prevPoint = point;
}
}
Запустив получим следующий результат:

Массив звезд
Теперь давайте представим что нам нужно вывести несколько звезд подряд в ряд или сетку из звезд. Для таких задач удобно иметь функцию, которая выводит звезду по заданным параметрам (позиция, размер, количество лучей, поворот, цвет и так далее). Давайте напишем первый вариант такой функции
public void DrawStar( Graphics gr,
float centerX, // X центра звезды
float centerY, // Y центра звезды
float outerRadius, // внешний радус звезды
float innerRadius, // внутренний радиус звезды
int n =5)
{
PointF? prevPoint = null;
var step = 360.0f / (n * 2); // шаг градусов
for (int i = 0; i <= n * 2; i++) // пробегаемся циклом по всем иднексам вершин звезды
{
float ang = i * step; // получаем из индекса угол путем домнажения на шаг step
var radians = ang * Math.PI / 180.0 - Math.PI / 2; // переводим в радианы и поворачиваем на -90°
var radius = (i % 2 == 0) ? outerRadius : innerRadius; // выбираем радиус исходя из текущего состояния флага even
// расчитываем координаты точки (x, y)
var x = centerX + radius * Math.Cos(radians);
var y = centerY + radius * Math.Sin(radians);
PointF point = new PointF((float)x, (float)y);
if (prevPoint != null)
gr.DrawLine(Pens.White, prevPoint.Value, point); // рисуем линию между точками
prevPoint = point;
}
}
Теперь пользуясь нашей функцией мы можем легко выводить звезды в цикле:
var starY = ClientRectangle.Height / 2;
var radius1 = 80;
var radius2 = 30;
var startX = 100;
var step = 180;
for ( int i = 0; i < 5; i++) {
var starX = startX+ i * step;
DrawStar(e.Graphics, starX, starY, radius1, radius2);
}Получим следющий результат:

Теперь давайте попробуем закрасить нашу звезду. Для этого требуется маленько переделать функцию отрисовки, воспользуеимя функцией FillPolygon для закрашивания прозивольного полигона (многоугольника). Поскольку данная функция трубует передать ей список точек, то мы больше не сможем рисовать линии на ходу как раньше. Сперва придется накопить в цикле все точки, и только после этого отправить их в функцию FillPolygon. Для накопления точек воспользуемя списком List<PointF>
Модифицированная функция которая может рисовать звезды с закрашиванием
public void DrawStar(Graphics gr,
float centerX, // X центра звезды
float centerY, // Y центра звезды
float outerRadius, // внешний радус звезды
float innerRadius, // внутренний радиус звезды
Pen? borderPen = null,
Brush? fillBrush = null,
int n = 5
)
{
List<PointF> points = new List<PointF>();
var step = 360.0f / (n * 2); // шаг градусов
bool even = false; // флаг указывающий какой из радиусов использовать на текущем шагу
for (int i = 0; i <= n * 2; i++) // пробегаемся циклом по всем иднексам вершин звезды
{
float ang = i * step; // получаем из индекса угол путем домнажения на шаг step
var radians = ang * Math.PI / 180.0 - Math.PI / 2; // переводим в радианы и поворачиваем на -90°
var radius = (i % 2 == 0) ? outerRadius : innerRadius; // выбираем радиус исходя из текущего состояния флага even
// расчитываем координаты точки (x, y)
var x = centerX + radius * Math.Cos(radians);
var y = centerY + radius * Math.Sin(radians);
PointF point = new PointF((float)x, (float)y);
points.Add(point);
}
if (fillBrush != null)
gr.FillPolygon(fillBrush, points.ToArray());
if (borderPen != null)
gr.DrawPolygon(borderPen, points.ToArray());
}
Теперь мы можем выводить закрашенные звезды:

Упражнения:
1. Вывести звезды по кругу
Теперь умея выводить звезды мы сможем потренироваться в следующем уроке при отрисовке флагов разных стран