Рисование контура и закраска области, ограниченной ломаной прямой

В предыдущем примере («Кораблик») мы использовали простые и очевидные методы рисования графических объектов класса Graphics, такие как  FillRectangle() — закрасить прямоугольник, FillPie() — закрасить сектор и DrawEllipse() — нарисовать эллипс. Чуть более сложный метод  FillPolygon() — закрашенный полигон.

Постановка задачи: «Требуется нарисовать в небе несколько парапланов, имеющих разные цвета и размеры».

Обсуждение. Пусть все парапланы будут геометрически подобны друг другу. Для задания контура параплана нужно задать метод с параметрами, задающими его местоположение и некоторый характерный размер. Для простоты примера будем задавать цвета случайным образом.

Наши действия:

На форме (Form1) размером 900х400 поместим две кнопки «Закрась!» и «Нарисуй!», создадим для них и для Form1 обработчики событий Click.

Нам понадобятся объекты классов Graphics, SolidBrush, Pen, Point (точнее, это структура), Region и GraphicsPath (он задан в библиотеке System.Drawing.Drawing2D — дополнение к System.Drawing!).

Будем применять методы класса Graphics:
FillPath() — заполнить замкнутую область, заданную объектом класса GraphicsPath;
DrawPath() — нарисовать контур (может быть и не замкнутым), заданный объектом класса GraphicsPath;
ExcludeClip() — обновить вырезанную область данного объекта Graphics, чтобы исключить из нее часть, определяемую объектом класса Region, который создается через конструктор
Region gp = new Region(pp); где pp – объект класса GraphicsPath;
ResetClip() — сбросить вырезанную область(ти) и сделать ее бесконечной (условно, анти_ExcludeClip()).
Метод ExcludeClip(Region reg) закрывает для рисования указанную область, оставляя другие части холста видимыми для рисования, а метод ResetClip() отменяет этот запрет.

Полями класса Form1 объявим объекты:
Graphics g;   // холст
GraphicsPath pp; // контур фантома-дырки,
pp — объект класса GraphicsPath в System.Drawing.Drawing2D;
SolidBrush br;     // кисть

Рисовать будем купол параплана, имеющего разное местоположение и размеры. Его контур зададим объектом класса  GraphicsPath, для чего создадим метод:
private GraphicsPath paraplan(int x, int y, int r),
который возвращает контур купола параплана с центром в точке (x,y) и и характерным размером клетки r. Это ломаная прямая, проходящая через 8 точек.

Дополним конструктор Form1(), определим методы: Form1_Click(), button1_Click(), button2_Click().

Метод  public Color RandomColor() — «Случайный цвет» является вспомогательным. Он позволит менять цвета контуров и закраски. Написан для демонстрации применения класса Random из библиотеки System.

Примечание: В этом примере мы обошлись одним классом — Form1.
В этот класс, в дополнение ко всем полям, свойствам и методам класса, унаследованных от класса Form, мы добавили в качестве полей три объекта (холст, контур, кисть), дополнили конструктор класса без изменения имени (принцип полиморфизма), добавили три метода обработки событий, а также методы paraplan() и RandomColor().

Остальное вам должно быть понятно из комментариев в тексте программы (файл Form1.cs):

// Пример рисования замкнутых областей
// (C) В.Рычков, 2017
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
namespace парапланы
{
    public partial class Form1 : Form
    {
        Graphics g;         // холст
        GraphicsPath pp;    // контур фантома-дырки
        SolidBrush br;      // кисть 
        public Form1()      // конструктор формы
        {
            InitializeComponent();
            g = Graphics.FromHwnd(this.Handle);   // холст
            pp = paraplan(450, 130, 20);  // положение и размер
                                          // фантома-дырки
        }
       // метод возвращает контур с центром в точке (x,y) 
       // и размером клетки r. Нарисуйте его на бумаге.
        private GraphicsPath paraplan(int x, int y, int r)
        {
            int[,] pts = {  { x-4*r, y },
                            { x-2*r, y-r },
                            { x+2*r, y-r },
                            { x+4*r, y },   
                            { x+3*r, y+r },    
                            { x+r, y },    
                            { x-r, y },
                            { x-3*r, y+r }, 
                            { x-4*r, y }
                         };  // параплан через массив pts
            Point[] pt = new Point[9];  // массив точек для gp
            byte[] typ = new byte[9];   // массив соединений
            for (int p = 0; p < 9; p++)
            {
                pt[p].X = pts[p, 0];
                pt[p].Y = pts[p, 1];
                typ[p] = (byte)PathPointType.Line;  //ломаными,
                // PathPointType описан в System.Drawing.Drawing2D;
            }; 
            GraphicsPath gp = new GraphicsPath(pt, typ);    
            return gp;  // возвращаем внутренняя часть формы
        }
        // создает фантом-дырку и рисует поверх нее параплан
        private void Form1_Click(object sender, EventArgs e)
        {
        //  Метод обновляет отсеченную область gp
            Region gp = new Region(pp);
            g.ExcludeClip(gp);
        // Рисуем параплан большего размера
            GraphicsPath pp1 = paraplan(450, 180, 80); // контур
            br = new SolidBrush(RandomColor());        // кисть
            g.FillPath(br, pp1);                       // закраска
        }
        // сбрасывает дырку и рисует заплатку
        // кнопка "Закрась"
        private void button1_Click(object sender, EventArgs e)
        {
            g.ResetClip();  // сбрасывает вырезанную область и 
                   // делает ее бесконечной, анти_ExcludeClip();
            br = new SolidBrush(RandomColor());
            g.FillPath(br, pp);  // ставим заплатку
        }
        // рисует контур другого параплана, кнопка "Нарисуй"
        private void button2_Click(object sender, EventArgs e)
        {
            GraphicsPath pp1 = paraplan(150, 80, 30);
            // Рисуем параплан меньшего размера 
            Pen pen = new Pen(RandomColor(),4f);
            g.DrawPath(pen, pp1);
        }

        // случайный цвет - вспомогательный метод
        public Color RandomColor()     
        {
            int r, g, b;
            byte[] bytes1 = new byte[3];     // массив 3 цветов
            Random rnd1 = new Random();      // объект класса
            rnd1.NextBytes(bytes1);          // генерация массива 
            r = Convert.ToInt16(bytes1[0]);
            g = Convert.ToInt16(bytes1[1]);
            b = Convert.ToInt16(bytes1[2]);
            return Color.FromArgb(r, g, b);  // цвет через метод
        }
    }
}

Цвет парапланов меняется при нажатии на кнопки и при клике на форме. Пока не будет нажата кнопка «Закрась», маленький параплан  будет сохранять цвет фона. Поэкспериментируйте с программой.

параплан

Перейдем к рисованию сплайнами и кривыми Безье.

1 мысль о “Рисование контура и закраска области, ограниченной ломаной прямой”

Оставьте комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *