Наряду с перечисленными средствами Maple-языка для определения шрифтов заголовков графиков используется представленная выше процедура T_Font, обеспечивающая
(в отличие от стандартных средств языка) надежное переопределение шрифтов. Лежащий в основе создания данной процедуры алгоритм может быть распространен на целый ряд интересных прикладных задач программирования графики, связанных с модификациями {2D|3D}_ГО-структур.
Наряду со средствами создания структур данных для графических примитивов, модуль plottools поддерживает средства, обеспечивающие функции редактирования этих структур с целью изменения ряда характеристик описываемых ими ГО или изменения характеристик непосредственно для указанных ГО. К таким характеристикам можно отнести вращения ГО в пространстве, изменение его масштабов относительно выбранных измерений и др. На некоторых из них остановимся несколько детальнее.
По функции scale(ST, {Kx, Ky|Kx, Ky, Kz}) возвращается отредактированная графическая ST-структуры {2D|3D}-ГО, соответствующий объект которой относительно объекта исходной ST-структуры оказывается шкалирован (сжат/растянут) по осям координат согласно Kh-коэффициентам (h∈{x, y, z}) шкалирования. Наряду с графической структурой в качестве первого фактического аргумента scale-функции может выступать и непосредственно сам шкалируемый ГО. Использование scale-функции имеет смысл только с установкой опции scaling=constrained.
Специальным случаем scale-функции является модульная homothety-функция:
homothety({2D|3D}_ГО-структура, <Коэффициент> {, <Точка подобия})
определяющая коэффициент шкалирования заданной {2D|3D}_ГО-структуры одинаковым относительно осей координат. Третьим необязательным аргументом может выступать точка подобия. Функция возвращает указанным образом шкалированную графическую структуру данных, в последующем выводимую по display-функции.
Функция rotate(S, {α|α, β, γ}) по принципу действия подобна предыдущей, но с тем отличием, что возвращает отредактированную графическую S-структуру или непосредственно сам ГО, подвергнутые вращению относительно начала осей координат на указанные в радианах углы по соответствующим измерениям. В 2D-случае вращение объекта производится против часовой стрелки. В предыдущем фрагменте обе указанные функции применялись для преобразований создаваемых составных 3D-ГО.
Функция translate(ST, {a, b|a, d, c}) по принципу действия аналогична rotate-функции, но в отличие от второй производит параллельный перенос ГО (или соответствующее редактирование отвечающей ему ST-структуры) на указанные действительными значениями отрезки вдоль осей координат. По функции stellate(ST, h) возвращается отредактированная графическая ST-структура POLYGONS-типа, определяющая стеллированный (заострение граней) многогранник. При этом h-коэффициент стеллирования определяет как высоту граней-стелл, так и их направленность: при h < 1 стеллы направлены к центру многогранника, в противном случае от него. По функции формата вида: reflect({{2D|3D}-ГО|{2D|3D}_ГО-структура}, <Список опорных точек>)
производится генерация соответственно новых ГО или графической структуры, определяющих результат отражения {2D|3D}-ГО относительно заданного объекта (точка или прямая для 2D-случая либо точка, прямая или плоскость для 3D-случая), заданного списком определяющих его точек. Следующий фрагмент иллюстрирует примеры применения рассмотренных функций reflect и rotate:
> map(with, [plots, plottools]): F:= [TIMES, BOLD, 14]: G:= disk([1, 1], 0.3, thickness=2, color=gray): Kr:= [0, 1], [1, 0]: L:= line(Kr, linestyle=3, color=black, thickness=2): T:= textplot([0.9, 0.5,"<- Line of reflection"], color=black, font=F): display([G, reflect(G, [Kr]), L, T], scaling=constrained, axesfont=F); display([G, rotate(G, Pi/2)], scaling=constrained, axesfont=F);По модульной (plottools-модуль) функции следующего формата кодирования:
project({{2D|3D}-ГО|{2D|3D}_ГО-структура}, <Список опорных точек>)
производится генерация соответственно новых ГО или графической структуры, определяющих результат проектирования {2D|3D}-ГО относительно заданного объекта (прямая для 2D-случая либо прямая или плоскость для 3D-случая), заданного списком определяющих его точек. Наконец, по transform(Proc)-функции генерируется пользовательская процедура/функция, позволяющая редактировать графические структуры данных посредством применения ее ко всем точкам исходной графической структуры. В качестве полезного практического примера продемонстрируем принцип создания таких процедур на фрагменте погружения 2D-ГО в 3D-ГО:
> map(with, [plots, plottools]): F:= [TIMES, BOLD, 18]: Tr:= transform((x, y) -> [x, y, 0]):
T:=textplot([1, 0.4, "Coffee aroma"], color=black, font=F): Tr1:=transform((x,y) -> [x,y, -9]):
Ch:=hemisphere([0, 0, 0], 9, capped=false): BL:=disk([0, 0], 5, color=yellow): H:=ellipse([0, 0], 8, 9, color=green, filled=true, thickness=3): Art:= display(Ch, map(Tr, [BL, T]), Tr1(H), shading = ZHUE): Art; Cyl:= cylinder([5, 5, 4], 0.8, 4): Op:= [[6, 0, 0], [0, 6, 0], [0, 0, 7]]:display(Cyl, polygon(Op), project(Cyl, Op), orientation = [-12, 71], axes = normal, axesfont = F, lightmodel = light2, thickness = 2, shading = none);
Принцип организации такого механизма достаточно прозрачен и особых пояснений с учетом вышесказанного не требует. Читателю в качестве весьма полезного упражнения рекомендуется практически рассмотреть подобные графические примеры. Второй пример фрагмента иллюстриует применение project-функции для вывода результата проектирования цилиндра на плоскость. Таким образом, функции changecoords, project, scale, reflect, rotate, stellate, homothety, transform и translate определяют полезные процедуры преобразования уже готового ГО либо его структуры.
Дополнительные замечания. Как и любое программное средство пакет Maple постоянно развивается, пополняясь как новыми средствами, так и модифицируя уже существующие. В этом отношении можно отметить и графические средства пакета. Прежде всего, начиная с релиза 9, введен дополнительный формат модульной animate-функции, а именно: animate(<Функция>, [<Аргументы>], t={a..b|L}, ...)
где функция определяет Maple-процедуру, генерирующую графический {2D|3D}-объект, второй аргумент определяет передаваемые ей фактические аргументы, параметр анимации t может определяться диапазоном действительных констант либо списком действительных или комплексных констант. При этом, animate-функция обеспечивает анимацию для любой plot-функции пакета, однако только по одному параметру. Тогда как наши процедуры Animate2D и Animate3D [41,103,109] позволяют анимировать функциональные зависимости по любому конечному числу параметров. Первая из указанных процедур была представлена выше. Следующий фрагмент представляет примеры организации анимации одной и той же функциональной зависимости тремя способами, а именно: на основе соответствующей установки insequence-опции display-функции, animateфункции первого формата и animate-функции расширенного формата:
> plots[display]([seq(plot(sin(x), x = 0..k, thickness = 2, color = green, axesfont = [TIMES,
BOLD, 12]), k = [0.01*p$p = 1..628])], insequence = true);
> plots[animate](sin(0.01*k*x), x = 0..2*Pi, k = 1..628, thickness = 2, color = green, axesfont = [TIMES, BOLD, 12]);
> plots[animate](plot, [sin(k*x), x = 0..2*Pi, thickness = 2, color = green, axesfont = [TIMES,
BOLD, 12]], k = [0.01*p$p = 1..628]);
> plots[animate](plot, [sin(k*x), x = 0..2*Pi, thickness = 2, color = green, axesfont = [TIMES, BOLD, 12]], k = [0.01*p$p=1..628], background = plot({1, -1}, x = 0..2*Pi, thickness = 3, color = [red, red]));
При использовании третьего способа анимации в процессе его отображается динамика изменения значений t-параметра анимации, позволяя более четко отслеживать динамику фреймов в процессе анимирования объекта. Более того, третий способ анимации допускает использование опции background=Р, где Р – {PLOT|PLOT3D}-объект либо генерирующая его графическая процедура. В этом случае такой объект становится фоном, на котором происходит анимация основного объекта, определяемого вторым фактическим аргументом. Четвертый пример предыдущего фрагмента иллюстрирует указанную возможность. Естественно, режим анимации на фоне других объектов можно производить и другими способами, как это мы и делали ранее и как это иллюстрирует следующая достаточно простая процедура animbkgd:
local k; plots display[Первый аргумент Х процедуры определяет список {PLOT|PLOT3D}-объектов, подлежащих анимации на фоне {PLOT|PLOT3D}-объектов, определяемых списком либо множеством Y. При этом, вызов процедуры animbkgd(X, Y {, опции}) может содержать дополнительные графические опции, обеспечивающие соответствующее дооформление результирующего анимируемого объекта. Пример фрагмента иллюстрирует сказанное. Наш подход более универсален, распростаняясь на любые графические объекты, не обязательно отвечающие функциональным зависимостям. Между тем, третий способ анимации более удобен для работы с {2D|3D}-мерными функциональными зависимостями.
Начиная с Maple 9, пакет дополнен возможностью интерактивного построения графиков на основе алгебраических выражений, а именно. Щелчком правой клавиши по алгебраическому выражению Output-параграфа текущего документа открываем окно, в котором по цепочке команд Plots –> Plot Builder открываем подокно «Interactive Plot Builder», через поля которого можно создавать требуемого оформления графический объект на основе исходного выражения с последующим его выводом. На данном аспекте внимания не концентрировалось, ибо на наш взгляд, он не относится к вопросам программирования в Maple и, во-вторых, он не дает особых преимуществ. Проще скопированное в СБО из Output-параграфа выражение поместить в конструкцию следующего вида
{plot|plot3d}(<Выражение>, ...)
Input-параграфа и вычислить ее. Сразу же получаем искомый графический объект, желаемое оформление которого производится оперативно и весьма просто.
Наряду с рассмотренными графическими средствами как стандартными, так и определяемыми пакетными модулями plots и plottools, ряд других модулей также предоставляет средства для работы с более специфическими графическими объектами, среди таких модулей (обладающих графическими средствами) можно отметить следующие: