Персональный сайт
Романа Парпалака

Заметки
 
Блог
 
Программы
 
Фото
ГлавнаяЗаметкиТехнологииПрограммирование → Delphi и EPS

Delphi и EPS

4 декабря 2009 года

Векторная графика

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

Разрабатывая одну программу на Delphi, я оказался в похожей ситуации. Сначала я сделал экспорт в BMP размером 10000*10000. Но это не самое красивое и удобное решение, и я захотел перейти к векторным изображениям. Встроенных средств для работы с векторной графикой в Delphi нет. Бесплатных дополнений я не нашел. Мне пришлось написать свою библиотечку.

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

Еще одно достоинство векторных форматов — их можно просматривать в специальных программах, приближать отдельные области и т. д. При этом у программы, создавшей такой файл, совсем не обязательно делать графический интерфейс. SVG-файлы можно просматривать в Опере (правда, увеличение будет максимум десятикратным), а файлы EPS — в GSView.

Библиотека delphi_eps

Чтение обзора формата EPS и просмотр простых EPS-файлов, созданных в векторном редакторе, показывают, что сгенерировать EPS-файл нетрудно. Мы рассмотрим этот процесс на примере закрашенного многоугольника.

Итак, просматривая простейший EPS-файл, находим, что некоторому многоугольнику (точнее, треугольнику) соответствуют строчки

gsave 1 0 0 setrgbcolor newpath 141 301 moveto 131 311 lineto 141 321 lineto 141 301 lineto closepath fill grestore

Команда setrgbcolor отвечает за цвет заливки. Три числа — доли красного, зеленого и синего цвета (от 0 до 1). Вершины многоугольника задаются командами moveto и lineto.

Команды вроде setrgbcolor или lineto мы будем хранить в шаблоне — текстовом файле. Вот его фрагмент:

<!-- filled_polygon --> gsave *COLOR* newpath *BODY* closepath fill grestore <!-- filled_polygon --> <!-- lineto --> *X* *Y* lineto <!-- lineto --> <!-- moveto --> *X* *Y* moveto <!-- moveto --> <!-- color --> *R* *G* *B* setrgbcolor <!-- color -->

Этот файл легко прочитать (функции explode и str_replace максимально приближены к аналогичным функциям из PHP: первая разбивает строку на части по разделителю, а вторая производит замену одной подстроки на другую):

var sa, sa2: TStrings; s: string; ... s := ''; sa := TStringList.Create; try sa.LoadFromFile(filename); s := sa.text; finally sa.Free; end; s := str_replace(#10, '', s); sa2 := explode('<!-- filled_polygon -->', s); if sa2.Count <> 3 then exit; polygon_pattern := trim(sa2[1]) + #13; sa2.Free; sa2 := explode('<!-- lineto -->', s); if sa2.Count <> 3 then exit; lineto_pattern := trim(sa2[1]) + #13; sa2.Free; sa2 := explode('<!-- moveto -->', s); if sa2.Count <> 3 then exit; moveto_pattern := trim(sa2[1]) + #13; sa2.Free;

Когда шаблоны прочитаны, в них легко вставить настоящие данные:

type TPointF = record x, y: double; end; procedure TEPS.SetFillColor(const r, g, b: double); begin fill_color := color_pattern; fill_color := str_replace('*R*', MyFloatToStr(r), fill_color); fill_color := str_replace('*G*', MyFloatToStr(g), fill_color); fill_color := str_replace('*B*', MyFloatToStr(b), fill_color); end; procedure TEPS.FillPolygon(const points: array of TPointF); var i: integer; s, current_path: string; begin if Length(points) < 2 then exit; s := moveto_pattern; s := str_replace('*X*', MyFloatToStr(points[0].x), s); s := str_replace('*Y*', MyFloatToStr(points[0].y), s); current_path := s; for i := Length(points) - 1 downto 0 do begin s := lineto_pattern; s := str_replace('*X*', MyFloatToStr(points[i].x), s); s := str_replace('*Y*', MyFloatToStr(points[i].y), s); current_path := current_path + s; end; s := str_replace('*BODY*', current_path, polygon_pattern); s := str_replace('*COLOR*', fill_color, s); current_body := current_body + s; end;

Переменная fill_color содержит текущий цвет заполнения областей. В переменной current_body собирается всё «тело» EPS-файла.

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

var tr: array[0..2] of TPointF; ... eps.SetFillColor(1, 0, 0); tr[0].x := 141; tr[0].y := 301; tr[1].x := 141; tr[1].y := 321; tr[2].x := 131; tr[2].y := 311; eps.FillPolygon(tr);

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

В архиве с библиотечкой есть пример использования, более приближенный к реальности. Мне как-то потребовалось нарисовать касательные к параболе, расположенные под равными углами друг к другу. Несколько строчек на Паскале — и нужная картинка уже сохранена в файл. Дальше с ней можно делать всё, что угодно, например, привести ее здесь в качестве примера.

Сгенерировано Delphi EPS

Скачать

delphi_eps.zip, 3 Кб.

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

Ваше имя:


Ваш e-mail:





Комментарий:

Для выделения используйте следующий код: [I]курсив[/I], [B]жирный[/B].
Цитату оформляйте так: [Q = имя автора]цитата[/Q] или [Q]еще цитата[/Q].
Ссылку начните с http://. Других команд или HTML-тегов здесь нет.


Сколько будет 71+6?


Еще в разделе «Программирование»:

Блог о кино

наверх