|
|
|
Простой векторный графический редактор (разбор полётов)16.11.2018, 09:22. Показов 36025. Ответов 127
Метки векторная графика (Все метки)
Всем привет! Меня зовут ashsvis и я программист...
Я пытался бороться с этим "недугом", но эта привычка затягивает меня всё глубже... (шутка) Короче, для тех кто не в теме: я пытаюсь сделать простой векторный графический редактор. Сначала я выпустил цикл статей по этому поводу (см. https://www.cyberforum.ru/blog... tegory389/) Получилась начальная версия редактора (можно забрать по ссылке в статье https://www.cyberforum.ru/blog... g5533.html) Первая версия, она известно какая и, благодаря критике моих более опытных коллег, была несколько переработана, с целью улучшить её (а с какой-же ещё?) и получилась версия вторая (можно забрать по ссылке в статье https://www.cyberforum.ru/blog... g5536.html) После второй версии мне намекнули, что я начал движение вообще не в ту сторону и предложили выложить в отдельную тему, на стол прозектора, так сказать. Что я и делаю. Подключайтесь к обсуждению, господа программисты. Давайте выведем меня на чистую воду... ![]() Добавлено через 3 часа 28 минут [для "затравки" дискуссии] У меня тут появилась мысль, как ни странно, что если попытаться перевести логику работы редактора из WinForms в WPF, то с текущей моделью это будет сделать сложновато. Там ведь (в WPF) всё другое, даже точки Point на основе double...
0
|
|
| 16.11.2018, 09:22 | |
|
Ответы с готовыми решениями:
127
Написать простой графический редактор электрических цепей Простой графический редактор, как сохранять изображение Создать простой векторный графический редактор |
|
|
||||||||||||||||||||||
| 16.11.2018, 12:19 | ||||||||||||||||||||||
|
Во-первых, давайте определимся с ТЗ.
Раз вы его не задали, сформулирую я. Нужно создать простой(?) векторный редактор, который позволяет: 1) Строить геометрические фигуры произвольной формы, включая: квадраты, окружности, прямоугольники, правильные n-угольники, произвольные многоугольники, ломаные линии, кривые Базье и текст. 2) Менять стиль границы и заливки фигур. 3) Менять местоположение, размеры фигур, а также поддерживать вращение фигур. Трансформации должны поддерживаться как для одиночной фигуры, так и для набора выделенных фигур. 4) Поддерживать минимальную инфраструктуру - чтение и сохранение файла, экспорт. Также, на вырост, по возможности нужно поддерживать undo/redo, слои, спецэффекты (свечение, размытие, тени). Далее, предлагаю подумать о модели данных. Центральное понятие - фигура. Фигура - это то что рисуется, имеет цвет, границу, форму. Фигуру можно перемещать и менять ее размеры. Для пользователя это выглядит как единое целое, но с программной точки зрения - это довольно сложный объект, который имеет ряд разных обязанностей. Можно выделить четыре разных обязанности: 1) Хранить форму фигуры 2) Хранить трансформацию фигуры (позицию, масштаб, вращение) 3) Хранить стиль фигуры (цвет границы, цвет заливки и т.д.) 4) Уметь рисовать себя на канве Если запихнуть все обязанности в один класс, мы получим большой слабоуправляемый, сильно связанный антипаттерн God Object. Это нам не хотелось бы. Поэтому предлагаю сделать класс Figure композитным объектом, который в себе содержит отдельные объекты, которые умеют выполнять вышеназванные функции:
Как известно, любые афинные преобразования векторов на плоскости можно описать одной матрицей 3*3 в обобщенных координатах. Поэтому в качестве Transform возьмем просто матрицу 3*3 которая будет содержать всю информацию о смещении, шклировании и вращении фигуры. Далее, объект Geometry должен нам вернуть GraphicsPath. Нам пока без разницы внутренне содержимое объекта Geometry, но на выходе он должен нам отдать сформированный объект GraphicsPath, который содержит форму того, что мы рисуем, и который можно просто отрисовать средствами GDI+. Поэтому класс Geometry сделаем абстрактным с одним публичным свойством Path:
Ну и наконец Renderer - это рисовальщик объекта на канве. Он должен содержать один метод Render. Его реализация достаточно проста и мы можем ее сразу написать:
Плюсы данной модели: 1) Нет GodObject-ов, форма, стиль, трансформации и рендеринг разнесены по разным классам. 2) Абстрактный класс Geometry может содержать любой графический контент, включая полигоны, линии, текст или даже внешний векторный рисунок. При этом, вся геометрия инкапсулирована, наружу дается только то, что нужно для рендеринга - GraphicsPath. 3) Трансформации хранятся отдельно, легко модифицируются. При этом, сама геометрия не меняется. 4) Классы хорошо изолированы друг от друга (кроме класса Renderer, который понятное дело, должен соединять все компоненты вместе). 5) Бонусом получаем то, что мы можем менять компоненты фигуры, независимо друг от друга. Например, вместо геометрии Квадрат, можно подставить геометрию Круг. При этом, трансформации и стиль фигуры останутся прежними, просто вместо квадрата, в фигуре будет рисоваться круг. Такого трудно было бы добиться, если бы мы наследовали фигуры от базового класса, как это обычно делают в детских учебниках (аля класс Square наследуется от Figure). Кроме того, мы можем легко присваивать стиль рисования, копировать стили из одной фигуры в другую, и даже использовать один стиль для нескольких фигур. Нужно отметить, что эта модель наверное не идеальна. И вообще возможно великое множество разных подходов и разных реализаций. Но если прикинуть, то все заявленные в ТЗ требования в ней могут быть выполнены. Фигуры и текст может рендерить? Может. Вращать объекты может? Может. Стили задавать можно? Можно. Кисти типа GradientBrush делать можно? Можно. Сериализвать объекты - можно, генерировать различные маркеры для разных геометрий - можно. Могут возникнуть какие-то проблемы, но в целом такая модель справляется с ТЗ. То есть она как минимум приемлема. ashsvis, Все таки, нужно сделать репозиторий на github. Это реально бы упростило дело. Если хотите, могу я создать.
6
|
||||||||||||||||||||||
|
|
||
| 16.11.2018, 12:53 [ТС] | ||
|
Storm23, спасибо за развёрнутый ответ!
потом какой-то репозиторий пытался удалить. В общем, как обезьяна перед .... Всё на английском, идеологии пока не пойму. Вот что получилось: https://github.com/ashsvis/Sim... tor-editor. В VS вроде как подключил и даже сделал 2 коммита. Хотел один из тестовых репозиториев удалить и не знаю, как. Но всё на автомате делал, нужно разбираться конкретно... А вообще бы я хотел заливать файлы как-то без VS, если это возможно. Посоветуйте, как поступить. Но, что очень важно для меня, я хотел бы код править сам и заливать сам, ибо материала в Вашем этом посте уже пока достаточно для начала работы. Спасибо за ТЗ, отличное получилось, мог ли я себе позволить выдать Вам ТЗ... В общем, я приступаю.
1
|
||
|
|
|
| 16.11.2018, 13:17 | |
|
ashsvis, качайте Git for Windows и читайте https://git-scm.com/book/ru/v2
1
|
|
|
|
|||
| 16.11.2018, 13:26 | |||
![]() И да, разбейте код по папкам. Эта мешанина их контролов, вспомогательных файлов и файлов модели - режет глаз. А модель так и вообще можно в отдельный проект вынести.
2
|
|||
|
|
||
| 16.11.2018, 17:49 | ||
|
Мы же только начали модель строить. А вы уже пошли что-то писать? Вы пытаетесь натянуть сову на глобус? Ну то есть просто впихнуть эту модель в вашу программу? PS Посмотрел, уже налеплено куча классов, уже пошло поехало... Брррр.... Вам не лень сейчас снова будет все переписывать?
0
|
||
|
|
|||
| 16.11.2018, 18:08 [ТС] | |||
|
Старый проект я не менял, только рассовал файлы по папкам и тренировался с гитхабом. Будьте уверены, паровоз я не обгоняю!
0
|
|||
|
|
|||||||
| 16.11.2018, 18:37 [ТС] | |||||||
|
Завести ещё один черновой репозиторий. (Я кажется начал понимать, как работать с репозиторием со страницы самого гитхаба). А вот через VS первый раз закидываю при создании проекта, а потом при обновлении ругается на отсутствие лицензии какой-то:
0
|
|||||||
|
|
||
| 16.11.2018, 18:42 | ||
|
0
|
||
|
|
|
| 16.11.2018, 19:22 [ТС] | |
|
Rius,
у меня уже есть хорошая книга: Петцольд. WPF базовый курс Добавлено через 38 минут Storm23, Рабочий репозиторий: https://github.com/ashsvis/VectorGraphicsEditor Содержит два проекта: заготовка с моделью и заготовка с интерфейсом формы (форма без кода). Я остановился и весь внимание...
0
|
|
|
|
|||||||||||||||||||||||||||||||||||||
| 16.11.2018, 21:06 | |||||||||||||||||||||||||||||||||||||
![]() Обратите внимание, я понятия не имею как делать это приложение. У меня нет готовых решений, которые я бы мог выложить. Я просто рассуждаю, как бы я делал это приложение. Ну ок, пойдем дальше. Во-первых по коду, который вы написали. Там уже есть ошибки. Возможно вы просто неправильно поняли смысл некоторых методов. Вот здесь:
Далее, вот здесь:
Ведь смысл каков - Geometry возвращает путь без учета преобразований. А GetTransformedPath должен вернуть путь уже с учетом преобразований. На самом деле этот путь можно получить и без этого метода (просто перемножив путь на трансформ), но поскольку получать этот путь нужно будет часто в программе, то лучше сделать отдельный метод для удобства. Аналогично нужно сделать метод GetBounds который вернет RectangleF вмещающего прямоугольника для фигуры. Т.о. GetTransformedPath должен выглядеть так:
Далее. На этом этапе лучше сделать небольшие unit-тесты. Тогда бы вы выяснили например, что ваша реализация GetPen - зациклена. Как делать простейшие unit-тесты смотрите в параллельной ветке здесь. Добавлено через 54 минуты Вернемся к нашей модели. Рассмотрим такую важную часть как класс Geometry. Мы бы могли сделать на каждую фигуру наследник от Geometry. Например class Sqaure: Geometry {...}. Но код этих классов будет очень простой и почти у всех одинаков. Поэтому смысла плодить кучу классов - нет.Вместо этого воспользуемся паттерном Строитель. Суть в том, что мы сделаем отдельный класс, назовем его FigureBuilder, который будет иметь ряд методов, которые будут создавать нужную геометрию для фигуры:
Методы для создания остальных фигур - думаю сделаете сами. Методы FigureBuilder могут быть вызваны прямо из интерфейса, для создания фигуры необходимой формы. Однако PrimitiveGeometry годится не для всех фигур. Например, нам нужна фигура типа Текст. Но строка текста задается (и меняется) пользователем. Поэтому GraphicsPath постоянно меняется и не может быть фиксированным, как в PrimitiveGeometry. Кроме того, текст зависит от шрифта и его размера. Поэтому, для текста создаем отдельный класс TextGeometry. Примерно такой:
Не забываем, что классы геометрии создаются только в FigureBuilder, поэтому там нужно создать соответствующие методы. Замечу также, что конструкторы PrimitiveGeometry, TextGeometry и т.д. объявлены как internal. Это сделано для того, что бы экземпляры этих классов можно было создавать только внутри FigureBuilder, и нельзя было создавать снаружи, из пользовательского кода.
0
|
|||||||||||||||||||||||||||||||||||||
|
|
||
| 16.11.2018, 21:43 [ТС] | ||
а когда остановился, то ждете предложений от меня ![]() Да, зацикливание я пропустил, а думал - как все сошлось, все свойства нужные нашел и подцепил. Я поработаю над новым материалом и выложу, что получается. Потом попробую продвинуться чуть далее самостоятельно. И потом обсудим. Спасибо! Ваши посты - как глоток свежего воздуха...
0
|
||
|
|
||||||||||||||||
| 17.11.2018, 10:06 [ТС] | ||||||||||||||||
|
Storm23, нужен совет.
Добавил в решение юнит тесты, начал добавлять примитивные класс и тут такое в тестах:
Здесь CheckInternalClassesConnection()
При создании фигуры я всегда вынужден создавать внутренние классы:
Пока остановился...
0
|
||||||||||||||||
|
|
||||||||
| 17.11.2018, 10:48 | ||||||||
0
|
||||||||
|
|
|||||||||||
| 17.11.2018, 13:31 [ТС] | |||||||||||
|
Storm23,
для сериализации пути нашёл такую штуку:
Надо будет ещё тест сейчас написать...
0
|
|||||||||||
|
|
|||||||
| 17.11.2018, 13:47 | |||||||
Только не нужно делать публичным полем Path. Сделайте его свойством. А еще лучше сделайте операторы приведения типа. Что бы можно было писать:
0
|
|||||||
|
|
|||||||
| 17.11.2018, 13:52 [ТС] | |||||||
|
Мдя... Тест провалился. Свойство Matrix тоже не сериализуется...
вот это:
0
|
|||||||
|
|
|||
| 17.11.2018, 13:54 | |||
|
Технические детали будут только отвлекать.
0
|
|||
| 17.11.2018, 13:54 | |
|
Помогаю со студенческими работами здесь
20
Векторный редактор карт Как создать векторный редактор? Графический редактор Графический редактор Графический редактор на С# Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |
|
Новые блоги и статьи
|
|||
|
Модель микоризы: классовый агентный подход 3
anaschu 06.01.2026
aa0a7f55b50dd51c5ec569d2d10c54f6/
O1rJuneU_ls
https:/ / vkvideo. ru/ video-115721503_456239114
|
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR
ФедосеевПавел 06.01.2026
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR
ВВЕДЕНИЕ
Введу сокращения:
аналоговый ПИД — ПИД регулятор с управляющим выходом в виде числа в диапазоне от 0% до. . .
|
Модель микоризы: классовый агентный подход 2
anaschu 06.01.2026
репозиторий https:/ / github. com/ shumilovas/ fungi
ветка по-частям.
коммит Create переделка под биомассу. txt
вход sc, но sm считается внутри мицелия. кстати, обьем тоже должен там считаться. . . .
|
Расчёт токов в цепи постоянного тока
igorrr37 05.01.2026
/ *
Дана цепь постоянного тока с сопротивлениями и напряжениями. Надо найти токи в ветвях.
Программа составляет систему уравнений по 1 и 2 законам Кирхгофа и решает её.
Последовательность действий:. . .
|
|
Новый CodeBlocs. Версия 25.03
palva 04.01.2026
Оказывается, недавно вышла новая версия CodeBlocks за номером 25. 03. Когда-то давно я возился с только что вышедшей тогда версией 20. 03. С тех пор я давно снёс всё с компьютера и забыл. Теперь. . .
|
Модель микоризы: классовый агентный подход
anaschu 02.01.2026
Раньше это было два гриба и бактерия. Теперь три гриба, растение.
И на уровне агентов добавится между грибами или бактериями взаимодействий.
До того я пробовал подход через многомерные массивы,. . .
|
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост.
Programma_Boinc 28.12.2025
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост.
Налог на собак: https:/ / **********/ gallery/ V06K53e
Финансовый отчет в Excel: https:/ / **********/ gallery/ bKBkQFf
Пост отсюда. . .
|
Кто-нибудь знает, где можно бесплатно получить настольный компьютер или ноутбук? США.
Programma_Boinc 26.12.2025
Нашел на реддите интересную статью под названием Anyone know where to get a free Desktop or Laptop?
Ниже её машинный перевод.
После долгих разбирательств я наконец-то вернула себе. . .
|