我正在努力纠正数学' 在 Asymptote 中正确绘制贝塞尔曲线的能力,我很难理解如何将 Mathematica 的规范转化为 Asymptote。我还没有找到关于如何在 Asymptote 中绘制贝塞尔曲线的易于理解的描述或教程。
因此,让我尝试通过一个基本示例来展示我想要做的事情:
Mathematica(实际上是数学):
Graphics[BezierCurve[{{0,0}, {1,1}, {2, -1}, {3,0}}]]
上述第一个例子翻译不正确:
usepackage("amsmath");
size(5.8333cm, 5.8333cm);
// BezierCurveBox
draw(0,.0.0), rgb(0, 0, 0)+linewidth(0.66667));
draw((0.,0.)..controls(155.56,213.89) and
(194.44,194.44)..(233.33,116.67),
rgb(0, 0, 0)+linewidth(0.66667));
上面,我给出了 Mathics 目前如何转换这一点。上面看到的错误之一似乎与平移控制点坐标以使图形在整个图像窗口中居中有关,同时不平移一些非控制点。而且在开始时似乎画了一个离群点。
我把这个保留了下来。但是在给出解决方案时,请随意完全忽略这一点,并从头开始描述具有与预期相同形状的东西。
那么我该如何解决这个问题,以及如何考虑做正确的翻译,就像上面的 Mathematica-to-Asymptote 示例一样?
继续关注:
我已经实现了接受的答案,并且适用于我给出的更简化的示例,但是当我将点数扩展到
pts = {{0, 0}, {1, 1}, {2, -1}, {3, 0}, {5, 2}, {6, -1}, {7, 3}};
看起来接受的答案与 Mathematica 所做的不同这里。
它看起来像是已接受答案的输出:
比 Mathematica 更受第 4 点的影响。我还注意到有一个 SplineDegree:
使用 SplineDegree->d 时,具有 d+1 个控制点的 BezierCurve 会产生一条简单的 d 阶贝塞尔曲线。使用较少的控制点时,会生成一条较低阶的曲线。使用较多的控制点时,会生成一条复合贝塞尔曲线。
正如@WillieWong 的评论中所发现的,Mathematica 每次绘制三个点的曲线,这似乎也是 SVG 处理点列表的方式。
如何处理高次曲线?
最后,我应该提到,Mathics 的下一个版本将会吸收这里的信息和帮助所带来的改进。
答案1
据我所知,你完全可以按照以下公式来做到这一点贝塞尔曲线。
像这样,
import graph;
pair Bezier(pair P[], real t)
{ // https://tex.stackexchange.com/a/554290/236162
pair Bezi;
for (int k=0; k <= P.length-1; ++k)
{
Bezi=Bezi+choose(P.length-1,k)*(1-t)^(P.length-1-k)*t^k*P[k];
}
return Bezi;
}
unitsize(1cm);
pair[] P={(0,0),(1,1),(2,-1)};
pair[] Q={(0,0),(1,1),(2,-1),(3,0)};
pair F(real t){return Bezier(P,t);}
pair G(real t){return Bezier(Q,t);}
draw(graph(F,0,1,350),red);
draw(operator --(... P));
draw(shift(0,-2)*graph(G,0,1,350),red);
draw(shift(0,-2)*operator --(... Q));
另请参阅文档:5 贝塞尔曲线
按此方式构造的贝塞尔曲线具有以下性质:
它完全包含在给定的四个点的凸包中。
它开始从第一个端点向第一个控制点前进,结束从第二个控制点向第二个端点前进。