Журнал LinuxFormat - перейти на главную

LXF78:MetaPost

Материал из Linuxformat
Перейти к: навигация, поиск

Часть 3. Компьютер не умеет читать ваши мысли, зато неукоснительно следует инструкциям. Евгений Балдин научит вас отдавать правильные команды и извлекать из этого выгоду.

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

Объекты picture

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

Для начала опять же воспользуемся миллиметровкой для отрисовки какого-либо рисунка, например, ракеты:
Img 78 104 1.jpg

Ракета может быть без выхлопа (rocket) и c выхлопом (firerocket). В процессе создания firerocket был использован рисунок самого выхлопа (fire).

%Файл picture.1.mp
%Ракета без выхлопа 10x12 Центр у стабилизаторов
 picture rocket;rocket:=nullpicture;
 addto rocket contour (-2,-1)--(-2,6)--(0,10)--(2,6)--(2,-1)--cycle
 withpen pencircle scaled 0.4 withcolor white;
 addto rocket  doublepath (-2,-1)--(-2,6)--(0,10)--(2,6)--(2,-1)--cycle
 withpen pencircle scaled 0.5;%Корпус
 addto rocket contour (-2,2.5)--(-4,1)--(-4.5,-3)--(-2,-3)--cycle
 withpen pencircle scaled 0.4 withcolor white;
 addto rocket  doublepath (-2,2.5)--(-4,1)--(-4.5,-3)--(-2,-3)--cycle
 withpen pencircle scaled 0.5;%левая дюза
 addto rocket contour (2,2.5)--(4,1)--(4.5,-3)--(2,-3)--cycle
 withpen pencircle scaled 0.4 withcolor white;
 addto rocket  doublepath (2,2.5)--(4,1)--(4.5,-3)--(2,-3)--cycle
 withpen pencircle scaled 0.5;%правая дюза
 addto rocket  doublepath (0,2.5)--(0,-3)
 withpen pencircle scaled 0.8;%центральная дюза
 %выхлоп
 picture fire;fire:=nullpicture;
 addto fire  doublepath (0,-4)--(0,-6)
 withpen pencircle scaled 0.3;%выхлоп 1
 addto fire  doublepath (-1.5,-4)--(-1.5,-6)
 withpen pencircle scaled 0.3;%выхлоп 2
 addto fire  doublepath (1.5,-4)--(1.5,-6)
 withpen pencircle scaled 0.3;%выхлоп 3
 addto fire  contour (-2.5,-6.5){dir 135}..(-4,-8)..
 {dir 50}(-1.2,-8.2){dir -110}..(0,-10)
 ..{dir 110}(1.2,-8.2){dir -50}..(4,-8)..{dir -135}(2.5,-6.5)--cycle
 withpen pencircle scaled 0.4 withcolor white;
 addto fire  doublepath (-2.5,-6.5){dir 135}..(-4,-8)..
 {dir 50}(-1.2,-8.2){dir -110}..(0,-10)
 ..{dir 110}(1.2,-8.2){dir -50}..(4,-8)..{dir -135}(2.5,-6.5)
 withpen pencircle scaled 0.3;%облако
 %ракета и выхлоп
 picture firerocket;firerocket:=rocket;
 addto firerocket also fire;

Прежде чем что-то добавить к картинке, её необходимо инициализировать. В MetaPost есть две определённые по умолчанию картинки: nullpicture — пустая картинка и currentpicture — текущая картинка. Пользуясь последней переменной, можно в любой момент сохранить результаты промежуточной отрисовки. Добавление элементов к картинке производится с помощью инструкции addto, после которой указывается картинка, к которой и добавляется тот или иной элемент. Путь добавляется с помощью инструкции doublepath, замкнутая область — с помощью инструкции contour, а другая картинка с помощью инструкции also.

Ранее был создан рисунок черепашки. Для его обозначения была выбрана переменная Turtle. Теперь с ней можно поработать, как с единым элементом, например, для иллюстрации задачи: «Черепашки расположены в углах правильного треугольника со стороной a и всегда ползут в направлении своей соседки против часовой стрелки со скоростью v. Когда они встретятся?»


Img 78 105 1.jpg

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

%Файл pic.mp
beginfig(17) ;
numeric u;u = 0.8mm;
numeric dphi; dphi=20;
   draw 30u*dir (90+dphi)--30u*dir (210+dphi)--30u*dir (330+dphi)--cycle 
   dashed evenly scaled 1u;
   draw Turtle rotated (-120+dphi) scaled 1u shifted (30u*dir (90+dphi));
   draw Turtle rotated dphi scaled 1u shifted (30u*dir (210+dphi));
   draw Turtle rotated (120+dphi) scaled 1u shifted (30u*dir (330+dphi));
endfig ;

Обратите внимание, что линия, соединяющая черепах, нарисована пунктиром. Определённая по умолчанию переменная evenly тоже является картинкой, поэтому её можно масштабировать с помощью декларации scaled. То есть, если вам нужен более широкий шаг пунктира, то вместо масштаба 1u можно указать 2u. Если вас не устраивает где располагаются штрихи у штриховки, то можно воспользоваться декларацией сдвига shifted.

Кроме шаблона evenly в MetaPost определён шаблон withdots, который позволяет рисовать кривую с помощью точек.

Вы можете определить свой шаблон для пунктира примерно следующим образом:

picture dash_center;
dash_center:=dashpattern(on 3 off 1.5 on 0.5 off 1.5);
draw 30u*dir (90+dphi)--30u*dir (210+dphi)--  30u*dir (330+dphi)--cycle dashed dash_center scaled 1u;

Функция dashpattern принимает список on/off с числовой информацией в какой момент рисовать/не рисовать. В этом примере определён шаблон для штрих-пунктирной линии, которая обычно используется для обозначения оси симметрии.

Трансформация

К задаче N 3 варианта ГГФ-51в требовалось изобразить L-образную трубку с водой. По условию, трубка сначала стояла вертикально, а потом была положена на стол.

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


Img 78 105 3.jpg

%Файл transform.mp
%пример использования slanted
beginfig(1) ;
numeric u;
u = 0.8mm;
%пробирка
cutdraw (0u,0u)--(20u,0u)--(20u,30u){dir 90}..
 {dir -90}(17u,30u)--(17u,3u)--(0u,3u)
 withpen pencircle scaled 0.5u;
drawdblarrow (23u,10u)--(23u,1u);
label.rt(btex \(h\) etex,1/2[(23u,10u),(23u,1u)]);
drawdblarrow (30u,30u)--(30u,1u);
label.lft(btex \(H\) etex,1/2[(30u,30u),(30u,1u)]);
picture Base;
Base:=currentpicture; %запоминаем
clearit; %очищаем текущую картинку
%рисуем воду когда пробирка будет наклонена
fill (15u,0u)--(20u,0u)--(20u,20u)--(17u,20u)--
 (17u,3u)--(15u,3u)--cycle withcolor 0.7white;
draw Base;
draw (12u,20u)--(20u,20u);draw (12u,10u)--(20u,10u);
drawdblarrow (14u,20u)--(14u,10u);
label.lft(btex \(d\) etex,(14u,16u));
picture Slant;
Slant=currentpicture; %запоминаем
clearit; %очищаем текущую картинку
%рисуем воду когда пробирка стоит
fill (5u,0u)--(20u,0u)--(20u,10u)--(17u,10u)--
 (17u,3u)--(5u,3u)--cycle withcolor 0.7white;
%отрисовываем пробирку
draw Base;
%отрисовываем пробирку и наклоняем её
draw Slant yscaled 2/3 slanted 1/2 shifted (40u,0u);
endfig ;

В примере применяется возможность сохранить текущее состояние с помощью currentpicture, а так же возможность полностью очистить текущую картинку с помощью инструкции clearit.


Img 78 105 2.jpg

Наклон вертикально стоящей пробирки происходит с помощью масштабирования yscaled и, собственно, наклона slanted.

MetaPost поддерживает следующие базовые линейные преобразования:

Персональные инструменты
купить
подписаться
Яндекс.Метрика