Как сделать фигуру в c

Добавил пользователь Дмитрий К.
Обновлено: 10.09.2024

Чтобы создавать красивые программы, нужно уметь рисовать фигуры. Начнём с основ. Сначала немного о системе координат. Нулевая точка окна в Processing находится в левом верхнем углу. Функция size() устанавливает размеры окна вашего скетча. Первый параметр присваивает значение встроенной переменной width (ширина), второй - встроенной переменной height (высота).

Для простых примеров мы пока временно не будем использовать функцию draw(), а весь код будем писать в функции setup().

Для рисования точки используется функция point(). Здесь также нужно указать два параметра - координаты точки.

Создадим окно размером 480 на 120 и поместим точку в центре (разделим размеры окна пополам).

Точка очень маленькая, разглядеть её сложно. Но вы постарайтесь. Зря что-ли старались.

Если вы хотите нарисовать точку в нижнем правом углу, то можете совершить ошибку, написав код.

На самом деле, нужно использовать координаты (479, 119), т.е. отнять единицу от размеров окна.

Чтобы нарисовать линию, нужно вызвать функцию line() c четырьмя параметрами - координаты начальной и конечной точки. А программа сама нарисует линию между ними. Разделим окно программы пополам. Удалим код для рисования точки, а вместо неё напечатаем другой код.

Получим следующую картинку.

line()

Подумайте, как нарисовать вертикальную линию. А по диагонали?

А что если нарисовать много параллельных линий по вертикали и горизонтали через одинаковые промежутки? Тогда получим сетку. Чтобы не повторять один и тот же код много раз, создадим отдельную функцию для рисования сетки, а в ней применим два цикла. Код получится намного короче.

Grid

А мы идём дальше и попробуем нарисовать треугольник. Для этого существует функция triangle() с шестью параметрами - координаты вершин треугольника. Наугад выбираем различные числа. Получился треугольник. Захотелось нарисовать рядом близнеца. Как это сделать? Чтобы сдвинуть второй треугольник вправо, прибавляем к параметрам, которые относятся к координате X, некоторое значение. Это будет смещением. Проверяем.

triangle()

Для многоугольников с четырьмя точками нужно уже восемь параметров. А функция называется quad().

quad()

Мы могли бы с помощью этой функции нарисовать и прямоугольник. Но писать восемь параметров слишком утомительно. К счастью, Processing немного понимает в геометрии. Если указать только координату первой точки, а потом ширину и высоту, то дальше программа сама всё рассчитает и нарисует. Функция называется rect(). Проверим.

rect()

Как нарисовать квадрат, вы сами догадаетесь.

Функция ellipse() нам уже знакома по первому уроку. Для рисования эллипса нужно указать центр, ширину и высоту. Стоит отметить, что можно указывать и отрицательные значения координат. Тогда может получиться, что в окне вы увидите только часть фигуры. Например, часть эллипса.

ellipse()

Также можно нарисовать дугу (сектор) с помощью функции arc(). Опять указываем центр, а также ширину и высоту. И вдобавок указываем начальный и конечный угол в радианах. Но с радианами работать не очень удобно. Что будет если указать значения 0 и 2? Для величин 180, 45, 90 и 360 градусов можно использовать готовые константы в радианах: PI, QUARTER_PI, HALF_PI, TWO_PI. Попробуем несколько вариантов.

Arc

Если вам известно значение в градусах, то можете его перевести в радианы с помощью функции radians().

Если вы рисуете много фигур, которые накладываются друг на друга, то сверху будет та фигура, чей код в вашей программе будет последним.

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

Функция strokeJoin() определяет вид соединения линий (углы), а функция strokeCap() - начальную и конечную точки линий.

За сглаживание отвечает функция smooth(). Существует парная ей функция noSmooth(), отключающая сглаживание.

Для цветов используются функции background(), fill(), stroke(), у которых нужно указать цвет в пределах от 0 (чёрный) до 255 (белый). Промежуточные величины будут оттенками серого. Можно отключить обводку (функция noStroke()) или сделать фигуру прозрачной функцией noFill():

Также можно указывать цвет. В этом случае используются три параметра:

Первая функция закрасит окно, вторая - фигуру, которая будет рисоваться после этой функции.

Можно использовать цветовую палитру через меню Tools | Color Selector.

Если добавить четвёртый параметр, то можно управлять прозрачностью.

Также можно нарисовать сложную фигуру, например, стрелку. Начните создание фигуры с функции beginShape(). Функция vertex() используется для определения x и y-координат фигуры. Функция endShape() ставится в конце описания фигуры и сигнализирует об окончании создания фигуры.

Arrow

Когда вы запустите пример, вы увидите, что первая и последняя точки не соединены. Чтобы сделать это, добавьте слово CLOSE как параметр функции endShape():

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

Звезда и цветок

Нарисуем звезду. Для неё создадим отдельную функцию star().

Функция звезды имеет три параметра: одно целое число для количества лучей и два параметра для внутреннего и внешнего радиуса звезды.

Попробуйте вынести Graphics g в глобальные переменные Graphics g; public Form1() < . если не поможет, напишу более достоверный способ.

1 ответ 1

не самый удачный, плохо расширяемый, но рабочий вариант:

Refresh() вызывает событие OnPaint(), которое перересовывает всю форму, на вашем месте я бы все фигуры, которые могут быть нарисованы, инкапсулировал в отдельный класс, а уже в OnPaint`e прорисовывал объект этого класса в зависимости от их наличия, т.е. у вас должен быть класс, описывающий Блок-Схему и логику работы с ней - получить/добавть/удалить/обновить элементы блок-схемы и т.п. и т.д, а любые изменения объекта сопровождались бы Refresh'ем.

Похожие

Для подписки на ленту скопируйте и вставьте эту ссылку в вашу программу для чтения RSS.

дизайн сайта / логотип © 2022 Stack Exchange Inc; материалы пользователей предоставляются на условиях лицензии cc by-sa. rev 2022.1.28.41306

Microsoft Logo

Gray Pipe

Приносим извинения. Запрошенное содержимое было удалено. Вы будете автоматически перенаправлены через 1 секунду.

Лучший отвечающий

Вопрос

Имеется объект Image, расположенный в PictureBox.
На этом объекте я рисую произвольную замкнутую фигуру. Это может быть корявый круг, шестиугольник, да все что угодно.
Вопрос:
Как мне по клику мыши закрасить область внутри этой фигуры в определенный цвет?
В интернете везде описывается способ закраски одноцветной области, но проблема в том, что область эта не одноцветная. Это область на любой загруженной картинке. Может быть фотография, картинка, все что угодно. В общем внутри обведенной области все пиксели различаются цветом.

Ответы

Один из способов

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

Устанавливаем некоторые переменные на уровне формы

Устанавливаем изображения для PictureBox

Связка Mouse Down-Move-Up для рисования на PicrureBox

Строим GraphicsPath и заполняем его цветом

Если границы области задаются каким-то другим способом, то, возможно, придется реализовать собственный алгоритм заливки с помощью GetPixel\SetPixel.

В любом случае общий принцип ясен: строим GraphicsPath для границы и заполняем его

Все ответы

Один из способов

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

Устанавливаем некоторые переменные на уровне формы

Устанавливаем изображения для PictureBox

Связка Mouse Down-Move-Up для рисования на PicrureBox

Строим GraphicsPath и заполняем его цветом

Если границы области задаются каким-то другим способом, то, возможно, придется реализовать собственный алгоритм заливки с помощью GetPixel\SetPixel.

В любом случае общий принцип ясен: строим GraphicsPath для границы и заполняем его

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

Т.е. по нажатию левой клавиши мыши пиксель окрашивается в определенный цвет. И если водить мышкой с зажатой левой клавишей, получается попиксельная закраска. Задумка такова: при клике правой клавишей мыши закрашивается вся область ограниченная этим определенным цветом.

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

Ммм. вроде где то так.



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

Помогите, кто может, я новичек еще в С++, а дали задание на лабу. Юзаю VC++ 6.0. Фигуры должны рисоваться просто на форме. Тип формы: диалоговое окно. Может есть у кого готовый класс (желательно с коментами, чтобы можно было хоть немного разобраться).

По идее, с такой лабой вы должны были изучать C++ не менее полугода. Филонишь, студент. По-моему, делать один класс, описывающий все три фигуры - глюк полнейший. Я бы сделал один базовый класс (типа Shape) с виртуальными методами Draw(), Move(), Rotate() и т. д., а конкретно круг, квадрад там сделал бы наследниками от Shape.
Готовый класс, чем-то похожий на твою лабу, по-моему есть у Джесса Либерти в его книге "Освой самостоятельно С++ за 21 день". Весьма лихая книжка, найдёшь - не пожалеешь.


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

Вот классы которые у меня описаны:

class Shape
public:
virtual void Draw(CWnd* wnd) = 0;
>;

class Rectangle: public Shape
virtual void Draw(CWnd* wnd);
>;

void Rectangle::Draw(CWnd* wnd)
CDC* pDC = wnd -> GetDC();
pDC -> Rectangle(20,20,10,10);
>

class Circle: public Shape
virtual void Draw(CWnd* wnd);
>;


И обработчик кнопки:

Не хочет рисовать, хоть убей.

Может я обработчик не в том месте пишу?
Можно как то мой пример переделать, чтобы совсем было просто?

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

По поводу - не хочет рисовать - так а где ты рисуешь то? Я не вижу например. Отрисовка нигде не вызывается.

И обработчик кнопки:

Не хочет рисовать, хоть убей.

Может я обработчик не в том месте пишу?
Можно как то мой пример переделать, чтобы совсем было просто?

насколько я понял ты МFC используешь, и если мне не изменяет память Invalidate() вызывает ОnPaint() в нем и если ты там не вызываешь прорисовку то ты куришь бамбук.

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


В нашем случае классам, производным от Shape, вполне позволительно проводить отрисовку самостоятельно. Более того, на мой взгляд, это наиболее эффективное решение, поскольку мы можем достаточно широко расширять как понятие "плоской фигуры", так и методов его представления на экране. Кроме того, я не вижу рациональных методов хранения информации о природе фигуры, позволяющих отображать примитив каркасу, а не экземпляру соответствующего объекта.

CSS Shapes позволяет создавать интересные и уникальные макеты, определяя геометрические фигуры, изображения и градиенты, вокруг которых может обтекать текстовое содержимое.


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

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

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

Внимание! CSS Shapes поддерживают браузеры Firefox, Chrome, Safari и Opera, а также мобильные браузеры, такие как iOS Safari и Chrome для Android. CSS Shapes не поддерживает IE и пока находится на рассмотрении в Microsoft Edge.

Первый взгляд на CSS Shapes

Текущая реализация CSS Shapes — это CSS Shapes Module Level 1, она в основном вращается вокруг свойства shape-outside . Это свойство определяет фигуры, вокруг которых может обтекать текст.

Учитывая, что есть свойство shape-outside, можно предположить, что существует и соответствующее свойство shape-inside, которое будет содержать текст внутри фигуры. Свойство shape-inside может стать реальностью в будущем, но в настоящее время оно является черновым в CSS Shapes Module Level 2 и не реализовано ни в одном браузере.

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

Базовые фигуры

Мы можем определить все виды базовых фигур в CSS, применяя следующие значения функций к свойству shape-outside :

  • circle()
  • ellipse()
  • inset()
  • polygon()

Чтобы добавить свойство shape-outside к элементу, он должен быть обтекаемым, а также у него должна быть установлена высота и ширина. Давайте рассмотрим каждую из четырёх основных фигур и продемонстрируем, как их можно использовать.

circle()

Начнём с функции circle() . Представьте себе ситуацию, что у нас есть круглый аватар автора, который мы хотим выровнять по левому краю и чтобы текст с описанием автора обтекал его. Для придания тексту круглой формы недостаточно использовать border-radius: 50% на элементе аватара; текст по прежнему будет считать аватар прямоугольным элементом.

С помощью circle() мы можем продемонстрировать, как текст может обтекать по кругу.

Начнём с создания класса circle для обычного элемента

Для нашего класса circle мы добавляем float со значением left , присваиваем ему одинаковую высоту и ширину и устанавливаем значение shape-outside как circle() .

Если взглянем на веб-страницу, она будет выглядеть так.


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


Если задать цвет фона или изображение для элемента, то вы увидите фигуру. Давайте попробуем это сделать.

К сожалению, установка фона для circle даёт нам прямоугольник, то самое, чего мы пытались избежать.


Мы можем ясно видеть обтекающий текст, но не саму фигуру элемента. Если желаем её отобразить, то нужно использовать свойство clip-path . Это свойство принимает те же значения, что и shape-outside , поэтому можем присвоить ему значение circle() .


В остальной части статьи я буду использовать clip-path , чтобы это помогло определить фигуру.

Функция circle() принимает необязательный параметр радиуса. В нашем случае радиус по умолчанию (r) составляет 50% или 100px. Использование circle(50%) или circle(100px) даст тот же результат, что мы уже сделали.

Можно заметить, что текст располагается сразу возле фигуры. Мы можем использовать свойство shape-margin , чтобы добавить поле к фигуре; значение может быть задано в px, em,% или в любой другой стандартной единице измерения CSS.

Вот пример circle() с радиусом 25% и добавлением shape-margin .


В дополнение к радиусу функция принимает позиционирование через at . Положение по умолчанию — центр круга, поэтому circle() будет явно записан как circle(50% at 50% 50%) или circle(100px at 100px 100px) ; значениями являются горизонтальное и вертикальное положение, соответственно.

Чтобы стало понятно как работает позиционирование, мы можем установить значение горизонтального положения равным 0 и получить идеальный полукруг.

Эта координатная система позиционирования известна как связанный блок.


Позже мы узнаем, как использовать изображение вместо фигуры или градиента. А теперь перейдём к следующей фигуре.

ellipse()

Похожей на circle() является функция ellipse() , которая создаёт эллипс. Для демонстрации добавим элемент с классом ellipse .

На этот раз мы установили разную высоту и ширину, чтобы сделать вертикально вытянутый овал.


Разница между ellipse() и circle() заключается в том, что эллипс имеет два радиуса— rx и ry или радиус по оси X и радиус по оси Y. Поэтому приведённый выше пример можно записать в таком виде:

Параметры позиционирования одинаковы для кругов и эллипсов. Радиусы, помимо того, что они являются единицей измерения, также включают farthest-side и closest-side .

closest-side указывает на длину от центра до ближайшей стороны связанного блока и наоборот, farthest-side указывает на длину от центра до самой дальней стороны связанного блока. Эти два значения не действуют, если не установлено положение, отличное от значения по умолчанию.

Вот демонстрация разницы перестановки closest-side и farthest-side для ellipse() со смещением на 25% по осям X и Y.



inset()

До сих пор мы имели дело только с круглыми фигурами, но можем вставлять и прямоугольники с внутренним отступом через функцию inset() .

В этом примере мы создаём прямоугольник размером 300px на 300px и отступом 75px со всех сторон. В итоге получится 150px на 150px с пространством вокруг 75px.


Мы можем видеть как вставлен прямоугольник, а текст игнорирует внутреннее пространство.


inset() также может принимать параметр border-radius со значением радиуса и текст будет учитывать скруглённые уголки, как в этом примере с 25px со всех сторон и скруглением 75px.


Подобно свойствам padding или margin , inset() принимает значение top right bottom left по часовой стрелке ( inset(25px 25px 25px 25px) ), использование только одного значения установит все четыре стороны одинаковыми ( inset(25px) ).

polygon()

Наиболее интересной и гибкой из функций является polygon() , который может принимать массив точек x и y для создания любой сложной фигуры. Каждый элемент в массиве представляет xi yi и будет записан как polygon(x1 y1, x2 y2, x3 y3. ) и т. д.

Наименьшим количеством наборов точек, которые мы можем применить к polygon() , является три, что создаёт треугольник.

В этой фигуре первая точка — 0 0, самая левая верхняя точка

. Третья и последняя точка — 200px 300px, что составляет 2/3 по оси X и снизу. Получившаяся фигура выглядит так:


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


Очевидно, вручную довольно трудно пытаться создать свои собственные сложные фигуры. К счастью, есть несколько инструментов, которые вы можете использовать для создания многоугольников. Firefox содержит встроенный редактор, который вы можете использовать, нажав на фигуру многоугольника в Инспекторе.


На данный момент для Chrome есть несколько расширений, которые вы можете использовать, такое как CSS Shapes Editor.

Многоугольники можно использовать для вырезания фигур вокруг изображений или других элементов. В данном примере мы создаём буквицу, нарисовав многоугольник вокруг большой буквы.


Изображения

Интересной особенностью CSS Shapes является то, что вам не всегда нужно явно определять фигуру с помощью функции. Вы также можете использовать адрес полупрозрачного изображения для определения фигуры и текст будет его автоматически обтекать.

Важно отметить, что используемое изображение должно быть CORS-совместимым, в противном случае вы получите ошибку подобную приведённой ниже.

Access to image at 'file:///users/tania/star.jpg' from origin 'null' has been blocked by CORS policy: The response is invalid.

Добавление изображения с того же сервера гарантирует, что вы не получите подобную ошибку.

В отличие от других примеров, мы будем использовать тег вместо

. На этот раз CSS простой — просто поместите url() в свойство shape-outside , как вы бы это сделали со свойством background-image .


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

Градиенты

Наконец, в качестве фигуры можно использовать градиенты. Они работают как изображения, и как с изображением, которое мы использовали выше, текст будет обтекать прозрачную часть.

С градиентами мы будем использовать одно новое свойство — shape-image-threshold . Оно определяет порог альфа-канала фигуры, другими словами, какой процент изображения будет считаться прозрачным.

Я сделала пример с градиентом, который разделен на 50%/50% между цветом и прозрачностью и установила значение shape-image-image как .5. Это означает, что все пиксели с непрозрачностью более 50% должны рассматриваться как часть изображения.


Можно увидеть, как градиент идеально разделён диагональю по центру прозрачного и непрозрачного цвета.

Заключение

В этой статье мы узнали о трёх свойствах CSS Shapes — shape-outside , shape-margin и shape-image-threshold . Мы также узнали, как использовать функции для создания кругов, эллипсов, прямоугольников и сложных многоугольников, вокруг которых может обтекать текст. Продемонстрировали, как фигуры могут отслеживать прозрачные фрагменты изображений и градиентов.

Все примеры из этой статьи можно найти в следующей демонстрации, а также скачать исходные файлы.

Читайте также: