2

在我的一门课程中,我得到了一项家庭作业,要求我们用谷歌搜索 Metapost 语言并找到该语言中方程求解功能的用途。在浏览了 Metapost 用户手册的前十几页之后,我发现它之所以有用只有一个原因,那就是“允许许多程序以主要的声明式风格编写”。除了说明它使编程更加“声明性”(据我理解,这意味着我们告诉语言该做什么而不是如何去做)我想不出任何其他原因说明方程求解是有用的。谁能帮我吗?

4

1 回答 1

3

这是一个说明如何在 MetaPost 中求解方程——以及就此而言的声明式编程——可能是有用的。

假设我们要画一个骰子

图片 0

为此,让我们首先定义一个宏,它将绘制骰子的一个面:一个s上面有数字的正方形。

def face (expr s) = image (begingroup
    pickup pencircle scaled 1pt;
    draw (0.5, 0.5) -- (0.5, 9.5) -- (9.5, 9.5) -- (9.5, 0.5) -- cycle;
    label (s, (5, 5));
endgroup) scaled 10 enddef;

现在我们可以绘制它并得到图片:

draw face ("1");

图 1

接下来,我们需要一个上脸和一个右脸。要绘制它们,我们将必须编写仿射变换来倾斜它们。这可能很棘手,因为唯一现成的用于倾斜的原始转换是slanted a将点(x, y)转换为(x + ay, y). 这是我们的图片倾斜1:

draw face ("2") slanted 1;

图二

然后(或者更确切地说,在此之前)我们必须按以下坐标之一进行缩放:

draw face ("2") yscaled 0.35 slanted 1;

图 3

同样的方法不适用于第三张脸:

draw face ("3") xscaled 0.35 slanted 1;

图 4

经过一番试验,我们找到了正确的代码:

draw face ("3") rotated 90 yscaled 0.35 slanted -1 rotated -90;

图 5

但为什么所有的乏味?我们确切地知道我们需要什么样的转变。一种自然的表达方式是使用原语。但是,如果这被证明是不直观的,就像我们最后一行一样,那么只指定平面的哪些点转换到哪些点可能会更舒服。

transform t;
(0, 0) transformed t = (0, 0);
(0, 1) transformed t = (0.35, 0.35);
(1, 0) transformed t = (1, 0);
draw face ("3") transformed t;

这基本上告诉 MetaPost:有一个 transform t,我们指定的三个点在它下面移动到我们指定的其他三个点。事实证明,这唯一地确定了平面变换,我们得到了相同的图片:

图 6

将所有这些放在一起(代码beginfig (7)在帖子末尾)让我们最终看到我们的死:

图 7

在这个简单的例子中,“坐标和方程”方法的难度与“原始变换”方法相当。现在,想象一下我们想要我们的立方体稍微倾斜。使用相同的声明性方法,仍然可以不调用 3D 几何(代码beginfig (8)在帖子末尾):

图 8


完整的程序如下。

prologues := 3;

def face (expr s) = image (begingroup
    pickup pencircle scaled 1pt;
    draw (0.5, 0.5) -- (0.5, 9.5) -- (9.5, 9.5) -- (9.5, 0.5) -- cycle;
    label (s, (5, 5));
endgroup) scaled 10 enddef;

beginfig (1)
    draw face ("1");
endfig;

beginfig (2)
    draw face ("2") slanted 1;
endfig;

beginfig (3)
    draw face ("2") yscaled 0.35 slanted 1;
endfig;

beginfig (4)
    draw face ("3") xscaled 0.35 slanted 1;
endfig;

beginfig (5)
    draw face ("3") rotated 90 yscaled 0.35 slanted -1 rotated -90;
endfig;

beginfig (6)
    transform t;
    (0, 0) transformed t = (0, 0);
    (0, 1) transformed t = (0, 1);
    (1, 0) transformed t = (0.35, 0.35);
    draw face ("3") transformed t;
endfig;

beginfig (7)
    transform t [];

    draw face ("1");

    (0, 0) transformed t[1] = (0, 0);
    (0, 1) transformed t[1] = (0.35, 0.35);
    (1, 0) transformed t[1] = (1, 0);
    draw face ("2") transformed t[1] shifted (0, 100);

    (0, 0) transformed t[2] = (0, 0);
    (0, 1) transformed t[2] = (0, 1);
    (1, 0) transformed t[2] = (0.35, 0.35);
    draw face ("3") transformed t[2] shifted (100, 0);
endfig;

beginfig (8)
    transform t [];
    pair Ox, Oy, Oz;
    Ox = (0.86, -0.21);
    Oy = (0.21, 0.86);
    Oz = (0.29, 0.44);

    (0, 0) transformed t[1] = (0, 0);
    (1, 0) transformed t[1] = Ox;
    (0, 1) transformed t[1] = Oy;
    draw face ("4") transformed t[1];

    (0, 0) transformed t[2] = (0, 0);
    (1, 0) transformed t[2] = Ox;
    (0, 1) transformed t[2] = Oz;
    draw face ("5") transformed t[2] shifted (Oy scaled 100);

    (0, 0) transformed t[3] = (0, 0);
    (1, 0) transformed t[3] = Oz;
    (0, 1) transformed t[3] = Oy;
    draw face ("6") transformed t[3] shifted (Ox scaled 100);
endfig;

end
于 2014-03-28T10:10:50.563 回答