metapost_MetaPost中的各种事情

metapost

MetaPost became the focus of these fantasies. MetaPost成为了这些幻想的焦点。

The main advantage of using MetaPost (or similar) solution is that every picture can be a sort of function of several variables. Such a picture can be quickly adjusted for any unforeseen circumstances of the layout, without disrupting important internal relationships of the illustration (something I was really concerned about), which is not easily achieved with more traditional tools. Also, recurring elements, all these spheres and springs, can be made more visually interesting than conventional tools would allow with the same time constraints.

使用MetaPost(或类似的)解决方案的主要优点是每张图片可以是多个变量的一种功能。 可以针对布局中任何无法预料的情况快速调整此类图片,而不会破坏插图的重要内部关系(我真正担心的事情),而这是使用传统工具无法轻易实现的。 而且,与传统工具在相同的时间限制下所允许的相比,可以使重复元素,所有这些球体和弹簧在视觉上更加有趣。

I wanted to make pictures with some kind of hatching, not unlike what you encounter in old books.

我想用一些阴影线来制作图片,这与您在旧书中遇到的情况不同。

First, I needed to be able to produce some curves of varying thickness. The main complication here is to construct a curve that follows the original curve at a varying distance. I used probably the most primitive working method, which boils down to simply shifting the line segments connecting Bezier curve control points by a given distance, except this distance varies along the curve.

首先,我需要能够产生一些不同厚度的曲线。 这里的主要复杂之处是构建一条曲线,该曲线在变化的距离后跟随原始曲线。 我可能使用了最原始的工作方法 ,归结为简单地将连接贝塞尔曲线控制点的线段移动给定距离,只是该距离沿曲线变化。

In most cases, it worked OK.

在大多数情况下,它工作正常。

范例程式码 (Example code)

From here on it is assumed that the library is downloaded and input fiziko.mp; is present in the MetaPost code. The fastest method is to use ConTeXt (then you don't need beginfig and endfig): \starttext

\startMPcode

input fiziko.mp;

% the code goes here

\stopMPcode

\stoptext

or LuaLaTeX:

\documentclass{article}

\usepackage{luamplib}

\begin{document}

\begin{mplibcode}

input fiziko.mp;

% the code goes here

\end{mplibcode}

\end{document}

beginfig(3);

path p, q; % MetaPost's syntax is reasonably readable, so I'll comment mostly on my stuff

p := (0,-1/4cm){dir(30)}..(5cm, 0)..{dir(30)}(10cm, 1/4cm);

q := offsetPath(p)(1cm*sin(offsetPathLength*pi)); % first argument is the path itself, second is a function of the position along this path (offsetPathLength changes from 0 to 1), which determines how far the outline is from the original line

draw p;

draw q dashed evenly;

endfig;

从这里开始,假设已 下载该库并 input fiziko.mp; 在MetaPost代码中。 最快的方法是使用ConTeXt(这样就不需要 beginfigendfig ): \starttext

\ startMPcode

输入fiziko.mp;

代码在这里

\ stopMPcode

\ stoptext

或LuaLaTeX:

\documentclass{article}

\ usepackage {luamplib}

\ begin {document}

\ begin {mplibcode}

输入fiziko.mp;

代码在这里

\ end {mplibcode}

\ end {document}

beginfig(3);

路径p,q; %MetaPost的语法可读性强,所以我将主要评论我的东西

p:=(0,-1 / 4cm){dir(30)} ..(5cm,0).. {dir(30)}(10cm,1 / 4cm);

q:= offsetPath(p)(1cm * sin(offsetPathLength * pi)); %第一个参数是路径本身,第二个参数是该路径位置的函数(offsetPathLength从0更改为1),它确定轮廓与原始线的距离

画p

画出q均匀地虚线;

endfig;

Two outlines can be combined to make a contour line for a variable-thickness stroke.

可以将两个轮廓组合起来以为厚度可变的笔划绘制轮廓线。

范例程式码 (Example code)

beginfig(4);

path p, q[];

p := (0,-1/4cm){dir(30)}..(5cm, 0)..{dir(30)}(10cm, 1/4cm);

q1 := offsetPath(p)(1/2pt*(sin(offsetPathLength*pi)**2)); % outline on one side

q2 := offsetPath(p)(-1/2pt*(sin(offsetPathLength*pi)**2)); % and on the other

fill q1--reverse(q2)--cycle;

endfig;

beginfig(4);

路径p,q [];

p:=(0,-1 / 4cm){dir(30)} ..(5cm,0).. {dir(30)}(10cm,1 / 4cm);

q1:= offsetPath(p)(1 / 2pt *(sin(offsetPathLength * pi)** 2)); 一侧轮廓%

q2:= offsetPath(p)(-1 / 2pt *(sin(offsetPathLength * pi)** 2)); %,另一方面

填充q1--反向(q2)-循环;

endfig;

The line thickness should have some lower bound, otherwise, some lines are going to be too thin to be properly printed and this doesn't look great. One of the options (the one I chose) is to make the lines which are too thin dashed, so that the total amount of ink per unit length remains approximately the same as in the intended thinner line. In other words, instead of reducing the amount of ink on the sides of the line, the algorithm takes some ink from the line itself.

线的粗细应该有一个下限,否则,有些线会太细而无法正确打印,这看起来并不好。 选项之一(我选择的一种)是将太细的线打成虚线,以使每单位长度的墨水总量与预期的较细线大致相同。 换句话说,该算法不是减少线条两侧的墨水量,而是从线条本身获取一些墨水。

范例程式码 (Example code)

beginfig(5);

path p;

p := (0,-1/4cm){dir(30)}..(5cm, 0)..{dir(30)}(10cm, 1/4cm);

draw brush(p)(1pt*(sin(offsetPathLength*pi)**2)); % the arguments are the same as for the outline

endfig;

beginfig(5);

路径p;

p:=(0,-1 / 4cm){dir(30)} ..(5cm,0).. {dir(30)}(10cm,1 / 4cm);

画刷(p)(1pt *(sin(offsetPathLength * pi)** 2)); %参数与大纲相同

endfig;

Once you have working variable-thickness lines, you can draw spheres. A sphere can be depicted as a series of concentric circles with the line thicknesses varying according to the output of a function that calculates the lightness of a particular point on the sphere.

一旦有了可变厚度的线,就可以绘制球体。 球体可以描述为一系列同心圆,线的粗细根据计算球体上特定点的亮度的函数的输出而变化。

范例程式码 (Example code)

beginfig(6);

draw sphere.c(1.2cm);

draw sphere.c(2.4cm) shifted (2cm, 0);

endfig;

beginfig(6);

画sphere.c(1.2cm);

绘制球体.c(2.4cm)偏移(2cm,0);

endfig;

Another convenient construction block is a “tube.” Roughly speaking it is a cylinder which you can bend. So long as the diameter is constant, it's pretty straightforward.

另一个方便的构造块是“管”。 粗略地说,它是可以弯曲的圆柱体。 只要直径恒定,就非常简单。

范例程式码 (Example code)

beginfig(7);

path p;

p := subpath (1,8) of fullcircle scaled 3cm;

draw tube.l(p)(1/2cm); % arguments are the path itself and the tube radius

endfig;

beginfig(7);

路径p;

p:=全圆的子路径(1,8),缩放3cm;

拉管.l(p)(1 / 2cm); %参数是路径本身和管半径

endfig;

If the diameter isn't constant, things become more complicated: the number of strokes should change according to the tube thickness in order to keep the amount of ink per unit area constant before taking the lights into account.

如果直径不是恒定的,则情况会变得更加复杂:行程数应根据管的厚度而变化,以便在考虑照明之前保持每单位面积的墨水量恒定。

范例程式码 (Example code)

beginfig(8);

path p;

p := pathSubdivide(fullcircle, 2) scaled 3cm; % this thing splits every segment between the points of a path (here—fullcircle) into several parts (here—2)

draw tube.l(p)(1/2cm + 1/6cm*sin(offsetPathLength*10pi));

endfig;

beginfig(8);

路径p;

p:= pathSubdivide(fullcircle,2)缩放3cm; %这个东西将路径的各个点(在此为全圆)之间的每个分段均分为几部分(在此为2)

l(p)(1 / 2cm + 1 / 6cm * sin(offsetPathLength * 10pi));

endfig;

There are also tubes with transverse hatching. The problem of keeping the amount of ink constant turned out to be even trickier in this case, so ofttimes such tubes look a tad shaggy.

也有带有横剖面线的管。 在这种情况下,保持墨水量恒定的问题变得更加棘手,因此,这种管有时看起来有点毛茸茸。

范例程式码 (Example code)

beginfig(9);

path p;

p := pathSubdivide(fullcircle, 2) scaled 3cm;

draw tube.t(p)(1/2cm + 1/6cm*sin(offsetPathLength*10pi));

endfig;

beginfig(9);

路径p;

p:= pathSubdivide(fullcircle,2)缩放3cm;

拉管.t(p)(1 / 2cm + 1 / 6cm * sin(offsetPathLength * 10pi));

endfig;

Tubes can be used to construct a wide range of objects: from cones and cylinders to balusters.

管子可用于构造各种物体:从圆锥体,圆柱体到栏杆。

范例程式码 (Example code)

beginfig(10);

draw tube.l ((0, 0) -- (0, 3cm))((1-offsetPathLength)*1cm) shifted (-3cm, 0); % a very simple cone

path p;

p := (-1/2cm, 0) {dir(175)} .. {dir(5)} (-1/2cm, 1/8cm) {dir(120)} .. (-2/5cm, 1/3cm) .. (-1/2cm, 3/4cm) {dir(90)} .. {dir(90)}(-1/4cm, 9/4cm){dir(175)} .. {dir(5)}(-1/4cm, 9/4cm + 1/5cm){dir(90)} .. (-2/5cm, 3cm); % baluster's envelope

p := pathSubdivide(p, 6);

draw p -- reverse(p xscaled -1) -- cycle;

tubeGenerateAlt(p, p xscaled -1, p rotated -90); % a more low-level stuff than tube.t, first two arguments are tube's sides and the third is the envelope. The envelope is basically a flattened out version of the outline, with line length along the x axis and the distance to line at the y. In the case of this baluster, it's simply its side rotated 90 degrees.

endfig;

beginfig(10);

l((0,0)-(0,3cm))(((1-offsetPathLength)* 1cm)移动(-3cm,0); %一个非常简单的圆锥

路径p;

p:=(-1 / 2cm,0){dir(175)} .. {dir(5)}(-1 / 2cm,1 / 8cm){dir(120)} ..(-2 / 5cm,1 / 3cm)..(-1 / 2cm,3 / 4cm){dir(90)} .. {dir(90)}(-1 / 4cm,9 / 4cm){dir(175)} .. {dir( 5)}(-1 / 4cm,9 / 4cm + 1 / 5cm){dir(90)} ..(-2 / 5cm,3cm); %栏杆的信封

p:= pathSubdivide(p,6);

画p-反向(p xscaled -1)-周期;

tubeGenerateAlt(p,p x缩放为-1,p旋转-90); %是比tube.t更底层的东西,前两个参数是tube的侧面,第三个参数是信封。 信封基本上是轮廓线的展平版本,沿x轴的线长为y,与线的距离为。 对于这种栏杆,只是其侧面旋转了90度。

endfig;

Some constructions which can be made from these primitives are included in the library. For example, the globe is basically a sphere.

库中包含一些可以由这些原语制成的构造。 例如,地球基本上是一个球体。

范例程式码 (Example code)

beginfig(11);

draw globe(1cm, -15, 0) shifted (-6/2cm, 0); % radius, west longitude, north latitude, both decimal

draw globe(3/2cm, -30.280577, 59.939461);

draw globe(4/3cm, -140, -30) shifted (10/3cm, 0);

endfig;

beginfig(11);

绘制地球仪(1cm,-15,0)平移(-6 / 2cm,0); 半径,西经,北纬%,均十进制

画球形(3 / 2cm,-30.280577,59.939461);

平移地球(4 / 3cm,-140,-30)(10 / 3cm,0);

endfig;

However, the hatching here is latitudinal and controlling line density is much more difficult than on the regular spheres with “concentric” hatching, so it's a different kind of sphere.

但是,这里的阴影是纬度的,并且控制线密度比使用“同心”阴影的常规球要困难得多,因此它是另一种球。

范例程式码 (Example code)

beginfig(12);

draw sphere.l(2cm, -60); % diameter and latitude

draw sphere.l(3cm, 45) shifted (3cm, 0);

endfig;

beginfig(12);

画球.l(2cm,-60); 直径和纬度百分比

画球.l(3cm,45)移动(3cm,0);

endfig;

A weight is a simple construction made from tubes of two types.

配重是由两种类型的管制成的简单结构。

范例程式码 (Example code)

beginfig(13);

draw weight.s(1cm); % weight height

draw weight.s(2cm) shifted (2cm, 0);

endfig;

beginfig(13);

画重。s(1cm); % 身高体重

拉伸重量.s(2cm)偏移(2cm,0);

endfig;

There's also a tool to knot the tubes.

还有一个打结管的工具。

示例代码。 为了简洁起见,只打一个结。 (Example code. For brevity's sake only one knot.)

beginfig(14);

path p;

p := (dir(90)*4/3cm) {dir(0)} .. tension 3/2 ..(dir(90 + 120)*4/3cm){dir(90 + 30)} .. tension 3/2 ..(dir(90 - 120)*4/3cm){dir(-90 - 30)} .. tension 3/2 .. cycle;

p := p scaled 6/5;

addStrandToKnot (primeOne) (p, 1/4cm, "l", "1, -1, 1"); % first, we add a strand of width 1/4cm going along the path p to the knot named primeOne. its intersections along the path go to layers "1, -1, 1" and the type of tube is going to be "l".

draw knotFromStrands (primeOne); % then the knot is drawn. you can add more than one strand.

endfig;

beginfig(14);

路径p;

p:=(dir(90)* 4 / 3cm){dir(0)} ..张力3/2 ..(dir(90 + 120)* 4 / 3cm){dir(90 + 30)} ..张力3/2 ..(dir(90-120)* 4 / 3cm){dir(-90-30)} ..张力3/2 ..周期;

p:= p缩放为6/5;

addStrandToKnot(primeOne)(p,1 / 4cm,“ l”,“ 1,-1,1”); %,首先,沿着路径p向名为primeOne的结添加一条宽度为1 / 4cm的线。 它沿路径的交点进入层“ 1 、、-1、1”,管的类型将为“ l”。

绘制knotFromStrands(primeOne); %,然后绘制结。 您可以添加多个分支。

endfig;

Tubes in knots drop shadows on each other as they should. In theory, this feature can be used in other contexts, but since I had no plans to go deep into the third dimension, the user interface is somewhat lacking and shadows work properly only for some objects.

结中的管子会互相照应地散下阴影。 从理论上讲,可以在其他情况下使用此功能,但是由于我没有计划深入研究第三维,因此用户界面有所欠缺,阴影仅适用于某些对象。

范例程式码 (Example code)

beginfig(15);

path shadowPath[];

boolean shadowsEnabled;

numeric numberOfShadows;

shadowsEnabled := true; % shadows need to be turned on

numberOfShadows := 1; % number of shadows should be specified

shadowPath0 := (-1cm, -2cm) -- (-1cm, 2cm) -- (-1cm +1/6cm, 2cm) -- (-1cm + 1/8cm, -2cm) -- cycle; % shadow-dropping object should be a closed path

shadowDepth0 := 4/3cm; % it's just this high above the object on which the shadow falls

shadowPath1 := shadowPath0 rotated -60;

shadowDepth1 := 4/3cm;

draw sphere.c(2.4cm); % shadows work ok only with sphere.c and tube.l with constant diameter

fill shadowPath0 withcolor white;

draw shadowPath0;

fill shadowPath1 withcolor white;

draw shadowPath1;

endfig;

beginfig(15);

路径shadowPath [];

boolean shadowsEnabled;

数字numberOfShadows;

shadowsEnabled:= true; 需要打开%阴影

numberOfShadows:= 1; 应指定阴影数量的%

shadowPath0:=(-1cm,-2cm)-(-1cm,2cm)-(-1cm + 1 / 6cm,2cm)-(-1cm + 1 / 8cm,-2cm)-循环; %阴影物体应为封闭路径

shadowDepth0:= 4 / 3cm; %就在阴影所落到的物体上方这么高

shadowPath1:= shadowPath0旋转-60;

shadowDepth1:= 4 / 3cm;

画sphere.c(2.4cm); %阴影仅适用于直径恒定的sphere.c和tube.l

用白色填充shadowPath0;

绘制shadowPath0;

用白色填充shadowPath1;

绘制shadowPath1;

endfig;

Certainly, you will need a wood texture (update: since the Russian version of this article was published, the first case of this library being used in a real project which I'm aware of has occurred, and it was the wood texture which came in handy, so this ended up not being a joke after all). How twigs and their growth affect the pattern of year rings is a topic for some serious study. The simplest working model I could come up with is as follows: year rings are parallel flat surfaces, distorted by growing twigs; thus the surface is modified by a series of not overly complex “twig functions” in different places and the surface's isolines are taken as the year ring pattern.

当然,您将需要木材纹理(更新:自从本文的俄语版本发布以来,该库在我所知的真实项目中使用的第一种情况已经发生了 ,这是后来出现的木材纹理派上用场,所以这最终不是一个玩笑。 细枝及其生长如何影响年轮的方式是一些认真研究的主题。 我能想到的最简单的工作模型如下:年轮是平行的平坦表面,会因树枝成长而变形。 因此,在不同位置通过一系列不太复杂的“细枝功能”对表面进行了修改,并将表面的等值线作为年轮样式。

范例程式码 (Example code)

beginfig(16);

numeric w, b;

pair A, B, C, D, A', B', C', D';

w := 4cm;

b := 1/2cm;

A := (0, 0);

A' := (b, b);

B := (0, w);

B' := (b, w-b);

C := (w, w);

C' := (w-b, w-b);

D := (w, 0);

D' := (w-b, b);

draw woodenThing(A--A'--B'--B--cycle, 0); % a piece of wood inside the A--A'--B'--B--cycle path, with wood grain at 0 degrees

draw woodenThing(B--B'--C'--C--cycle, 90);

draw woodenThing(C--C'--D'--D--cycle, 0);

draw woodenThing(A--A'--D'--D--cycle, 90);

eyescale := 2/3cm; % scale for the eye

draw eye(150) shifted 1/2[A,C]; % the eye looks in 150 degree direction

endfig;

beginfig(16);

数值w,b;

对A,B,C,D,A',B',C',D';

w:= 4厘米;

b:= 1 / 2cm;

A:=(0,0);

A':=(b,b);

B:=(0,w);

B':=(b,wb);

C:=(w,w);

C':=(wb,wb);

D:=(w,0);

D':=(wb,b);

画出woodenThing(A--A'-B'-B--cycle,0); %在A–A'–B'–B–循环路径内的一块木头,木纹为0度

画出woodenThing(B--B'-C'-C--cycle,90);

画出woodenThing(C--C'-D'-D--cycle,0);

画出woodenThing(A--A'-D'-D--cycle,90);

眼鳞:= 2 / 3cm; 眼睛比例

画眼(150)偏移1/2 [A,C]; %眼睛朝150度方向看

endfig;

The eye from the picture above opens wide or squints a bit and its pupil changes its size too. It may not make any practical sense, but mechanically similar eyes just look boring.

上图的眼睛张开或斜视,瞳Kong也改变了大小。 它可能没有任何实际意义,但是机械上相似的眼睛看起来很无聊。

范例程式码 (Example code)

beginfig(17);

eyescale := 2/3cm; % 1/2cm by default

draw eye(0) shifted (0cm, 0);

draw eye(0) shifted (1cm, 0);

draw eye(0) shifted (2cm, 0);

draw eye(0) shifted (3cm, 0);

draw eye(0) shifted (4cm, 0);

endfig;

beginfig(17);

眼鳞:= 2 / 3cm; 默认为1/2厘米

画眼(0)偏移(0cm,0);

画眼(0)偏移(1cm,0);

移开眼睛(0)(2cm,0);

移开画眼(0)(3cm,0);

移开画眼(0)(4cm,0);

endfig;

Most of the time the illustrations weren't all that complex, but a more rigorous approach would require solving many of the problems in the textbook to illustrate them correctly. Say, L'Hôpital's pulley problem (it wasn't in that textbook, but anyway): on the rope with the length

, suspended at the point a pulley is hanging; it's hooked to another rope, suspended at the point
with the weight on its end. The question is: where does the weight go if both the pulley and the ropes weigh nothing? Surprisingly, the solution and the construction for this problem are not that simple. But by playing with several variables you can make the picture look just right for the page while maintaining accuracy.

在大多数情况下,插图并没有那么复杂,但要采取更严格的方法,需要解决教科书中的许多问题才能正确地说明它们。 说,L'Hôpital的滑轮问题(不在那本教科书中,但无论如何):在长度上

,在该点暂停 滑轮挂着; 它挂在另一根绳子上,悬挂在该点上
与重量 在其末端。 问题是:如果滑轮和绳索都什么都不重,那么重量会流向何方? 令人惊讶的是,该问题的解决方案和构造并不那么简单。 但是通过玩几个变量,您可以使图片看起来恰好适合页面,同时保持准确性。

范例程式码 (Example code)

vardef lHopitalPulley (expr AB, l, m) = % distance AB between the suspension points of the ropes and their lengths l and m. “Why no units of length?”, you may ask. It's because some calculations inside can cause arithmetic overflow in MetaPost.

save A, B, C, D, E, o, a, x, y, d, w, h, support;

image(

pair A, B, C, D, E, o[];

path support;

numeric a, x[], y[], d[], w, h;

x1 := (l**2 + abs(l)*((sqrt(8)*AB)++l))/4AB; % the solution

y1 := l+-+x1; % second coordinate is trivial

y2 := m - ((AB-x1)++y1); % as well as the weight's position

A := (0, 0);

B := (AB*cm, 0);

D := (x1*cm, -y1*cm);

C := D shifted (0, -y2*cm);

d1 := 2/3cm; d2 := 1cm; d3 := 5/6d1; % diameters of the pulley, weight and the pulley wheel

w := 2/3cm; h := 1/3cm; % parameters of the wood block

o1 := (unitvector(C-D) rotated 90 scaled 1/2d3);

o2 := (unitvector(D-B) rotated 90 scaled 1/2d3);

E := whatever [D shifted o1, C shifted o1]

= whatever [D shifted o2, B shifted o2]; % pulley's center

a := angle(A-D);

support := A shifted (-w, 0) -- B shifted (w, 0) -- B shifted (w, h) -- A shifted (-w, h) -- cycle;

draw woodenThing(support, 0); % wood block everything is suspended from

draw pulley (d1, a - 90) shifted E; % the pulley

draw image(

draw A -- D -- B withpen thickpen;

draw D -- C withpen thickpen;

) maskedWith (pulleyOutline shifted E); % ropes should be covered with the pulley

draw sphere.c(d2) shifted C shifted (0, -1/2d2); % sphere as a weight

dotlabel.llft(btex $A$ etex, A);

dotlabel.lrt(btex $B$ etex, B);

dotlabel.ulft(btex $C$ etex, C);

label.llft(btex $l$ etex, 1/2[A, D]);

)

enddef;

beginfig(18);

draw lHopitalPulley (6, 2, 11/2); % now you can choose the right parameters

draw lHopitalPulley (3, 5/2, 3) shifted (8cm, 0);

endfig;

vardef lHopitalPulley (expr AB, l, m) = % distance AB between the suspension points of the ropes and their lengths l and m. “Why no units of length?”, you may ask. It's because some calculations inside can cause arithmetic overflow in MetaPost.

保存A,B,C,D,E,o,a,x,y,d,w,h,支持;

图片(

对A,B,C,D,E,o [];

路径支持;

数值a,x [],y [],d [],w,h;

x1:=(l ** 2 + abs(l)*((sqrt(8)* AB)++ l))/ 4AB; % 解决方案

y1:= l +-+ x1; %第二个坐标是微不足道的

y2:= m-((AB-x1)++ y1); %以及重量的位置

A:=(0,0);

B:=(AB * cm,0);

D:=(x1 * cm,-y1 * cm);

C:= D偏移(0,-y2 * cm);

d1:= 2/3厘米; d2:= 1厘米; d3:= 5 / 6d1; 皮带轮直径%,重量和皮带轮

w:= 2 / 3cm; h:= 1/3厘米; 木块的%参数

o1:=(unitvector(CD)旋转90缩放1 / 2d3);

o2:=(unitvector(DB)旋转90缩放1 / 2d3);

E:=不论[D移动o1,C移动o1]

=不论[D偏移o2,B偏移o2]; 滑轮中心百分比

a:=角度(AD);

support:= A移位(-w,0)-B移位(w,0)-B移位(w,h)-A移位(-w,h)-周期;

绘制woodenThing(support,0); %的木块,所有内容均已暂停

皮带轮(d1,a-90)移到E; %滑轮

绘制图像(

用厚纸画A-D-B;

用笔将D-C画得很厚;

)maskedWith(pulleyOutline移动E); %绳索应被滑轮覆盖

c(d2)移C移(0,-1 / 2d2); 球体重量百分比

dotlabel.llft(btex $ A $ etex,A);

dotlabel.lrt(btex $ B $ etex,B);

dotlabel.ulft(btex $ C $ etex,C);

label.llft(btex $ l $ etex,1/2 [A,D]);

)

enddef;

beginfig(18);

绘制lHopitalPulley(6,2,11/2); %现在您可以选择正确的参数

绘制lHopitalPulley(3,5/2,3)移(8cm,0);

endfig;

And what about the textbook? Alas, when almost all the illustrations and the layout were ready, something happened and the textbook was canceled. Maybe because of that, I decided to rewrite most of the functions of the original library from scratch (I chose not to use any of the original code, which, although indirectly, I was paid for) and put it on GitHub. Some things, present in the original library, such as functions for drawing cars and tractors, I didn't include there, some new features, e.g. knots, were added.

那教科书呢? las,当几乎所有的插图和布局都准备好了时,发生了什么事,教科书被取消了。 也许由于这个原因,我决定从头开始重写原始库的大多数功能(我选择不使用任何原始代码,尽管这是我间接付费的),然后将其放在GitHub上 。 原始库中存在一些内容,例如绘制汽车和拖拉机的功能,但我不包括在内,还添加了一些新功能,例如打结。

It doesn't run quickly: it takes about a minute to produce all the pictures for this article with LuaLaTeX on my laptop with i5-4200U 1.6 GHz. A pseudorandom number generator is used here and there, so no two similar pictures are absolutely identical (that's a feature) and every run produces slightly different pictures. To avoid surprises you can simply set randomseed := some number and enjoy the same results every run.

它无法快速运行:在我的i5-4200U 1.6 GHz笔记本电脑上使用LuaLaTeX生成本文的所有图片大约需要一分钟。 这里到处都使用伪随机数生成器,因此没有两张相似的图片是绝对相同的(这是一个功能),并且每次运行都会产生略有不同的图片。 为避免意外,您可以简单地将randomseed := some number设置randomseed := some number并在每次运行时享受相同的结果。

Many thanks to dr ord and Mikael Sundqvist for their help with the English version of this text.

非常感谢ord博士Mikael Sundqvist对本文英文版的帮助。

翻译自: https://habr.com/en/post/454376/

metapost

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值