How to| 创建带有样条基元的图形
Wolfram 语言提供了完全集成的样条图形基元,例如 Bézier 曲线、B-样条曲线和 B-样条曲面等. 样条基元支持全部范围的用户控件,例如任意次数和样条的一种有理形式等. 样条基元为创建复数图形提供了一种简单的方法.
BezierCurve 画出一条由给定控制点定义的复合 Bézier 曲线. 缺省时使用三次 Bézier 曲线:
Graphics[BezierCurve[{{0, 0}, {1, 1}, {2, 0}, {3, 1}}]]将 BSplineCurve 用于 Graphics 创建一条7个控制点组成的三次 B-样条曲线:
Graphics[BSplineCurve[{{1, -1}, {2, 1}, {3, -1}, {4, 1}, {5, -1}, {6, 1}, {7, -1}}, SplineDegree -> 4]]pts = Table[{i, (-1)^i}, {i, 7}];
Graphics[{Green, Line[pts], Red, Point[pts], Orange, BSplineCurve[pts]}]选项 SplineDegree 控制代表样条曲线的多项式的次数. 通常,次数越高,曲线越平滑.
这里,通过使用 Table 对 BSplineCurve 迭代,并且令 SplineDegree 由1到6变化,产生了6个具有相同控制点集合的不同样条曲线:
pts = Table[{i, (-1)^i}, {i, 7}];
Table[Graphics[{Green, Line[pts], Red, Point[pts], Orange, BSplineCurve[pts, SplineDegree -> d]}], {d, 1, 6}]选项 SplineKnots 为 B-样条曲线的形状提供详细控制. 如果不指定 SplineKnots 的值,Wolfram 语言按照这样的方式给出默认节点序列,即使生成的曲线整体平滑且端点以内插值替换:
pts = {{0, 0}, {0, 2}, {2, 3}, {4, 0}, {6, 3}, {8, 2}, {8, 0}};
Graphics[{Green, Line[pts], Red, Point[pts], Orange, BSplineCurve[pts]}]这是同一曲线,不同之处是默认的节点值显式给出. 第一个和最后一个
重复节点使得曲线经过节点,其中
是样条次数. 其余节点均匀分布:
Graphics[{Green, Line[pts], Red, Point[pts], Orange, BSplineCurve[pts, SplineKnots -> {0, 0, 0, 0, (1/4), (1/2), (3/4), 1, 1, 1, 1}]}]Graphics[{Green, Line[pts], Red, Point[pts], Orange, BSplineCurve[pts, SplineKnots -> {0, 0, 0, 0, (1/2), (1/2), (1/2), 1, 1, 1, 1}]}]当 SplineClosed 选项的设置为 True 时,Wolfram 语言将创建一条平滑闭合的 B-样条曲线:
pts = {{0, 0}, {0, (1/2)}, {1, (1/2)}, {1, 0}};Graphics[BSplineCurve[pts]]Graphics[BSplineCurve[pts, SplineClosed -> True]]选项 SplineWeights 可用于指定每个点的权重. 曲线将向权重较大的点拉近:
pts = Table[{i, (-1)^i}, {i, 7}];如果 SplineWeights 没有明确设置,Wolfram 语言为每个点指定相等的权重:
Graphics[{Green, Line[pts], Red, Point[pts], Orange, BSplineCurve[pts]}]注意曲线被拉向中间的点,SplineWeights 为该点指定的权重为5:
Graphics[{Green, Line[pts], Red, Point[pts], Orange, BSplineCurve[pts, SplineWeights -> {1, 1, 1, 5, 1, 1, 1}]}]从数学角度而言,非均匀的权重创建的是有理 B-样条函数, 也被称作 NURBS. NURBS 能够表示一般 B-样条不能表示的形状. 例如,通过设定 SplineWeights 为 w 中的值,设定 SplineKnots 为 k 中的值,使用 BSplineCurve 创建一个精确的圆环:
pts = {{.5, 0}, {1, 0}, {1, 1}, {.5, 1}, {0, 1}, {0, 0}, {.5, 0}};
w = {1, .5, .5, 1, .5, .5, 1};
k = {0, 0, 0, 1 / 4, 1 / 2, 1 / 2, 3 / 4, 1, 1, 1};Graphics[{Green, Line[pts], Red, Point[pts], Orange, BSplineCurve[pts, SplineWeights -> w, SplineKnots -> k]}]Graphics3D[BezierCurve[{{0, 0, 0}, {1, 1, 1}, {2, -1, 1}, {3, 0, 2}}]]Graphics3D[BSplineCurve[{{0, 0, 0}, {1, 1, 1}, {2, -1, 1}, {3, 0, 2}, {4, 1, 1}}]]通过将样条用 Tube 包装,可以创建三维管状样条曲线. 在这里,管半径为0.2:
Graphics3D[Tube[BezierCurve[{{0, 0, 0}, {1, 1, 1}, {2, -1, 1}, {3, 0, 2}}], 0.2]]Graphics3D[Tube[BSplineCurve[{{0, 0, 0}, {1, 1, 1}, {2, -1, 1}, {3, 0, 2}, {4, 1, 1}}], 0.2]]radii = {0.1, 0.2, 0.5, 0.2, 0.1};Graphics3D[Tube[BSplineCurve[{{0, 0, 0}, {1, 1, 1}, {2, -1, 1}, {3, 0, 2}, {4, 1, 1}}], radii]]BSplineSurface 创建一个由三维点阵定义的张量积 B-样条曲面:
pts = Table[{i, j, (-1)^i + j}, {i, 5}, {j, 5}];
Graphics3D[{BSplineSurface[pts], Red, Point /@ pts}]BSplineCurve 所有选项的工作方式相同. 然而,对于曲面,您可以对它们在每个参数方向上分别指定. 例如,下面的 SplineDegree 设置创建了一条 B-样条曲线,它在一个方向上是一次,而在另一个方向上是3次:
Graphics3D[{BSplineSurface[pts, SplineDegree -> {1, 3}], Red, Point /@ pts}]与 B-样条曲线相似,有理曲面,或称 NURBS 曲面,可以使用 SplineWeights 创建. 许多电脑辅助设计应用程序使用 NURBS 表示工业曲面. 下面的例子生成一个直角圆柱管:
pts = {{{.5, 0, -.5}, {0, 0, -.5}, {0, 1, -.5}, {.5, 1, -.5}, {1, 1, -.5}, {1, 0, -.5}, {.5, 0, -.5}}, {{.5, 0, 0.7}, {0, 0, 0.7}, {0, 1, 0.7}, {.5, 1, 0.7}, {1, 1, 0.7}, {1, 0, 0.7}, {.5, 0, 0.7}}, {{.5, 0, 0.9}, {0, 0, 0.9}, {0, 1, 1.5}, {.5, 1, 1.5}, {1, 1, 1.5}, {1, 0, 0.9}, {.5, 0, 0.9}}, {{.5, -0.1, 1}, {0, -0.1, 1}, {0, .5, 2}, {.5, .5, 2}, {1, .5, 2}, {1, -0.1, 1}, {.5, -0.1, 1}}, {{.5, -0.3, 1}, {0, -0.3, 1}, {0, -0.3, 2}, {.5, -0.3, 2}, {1, -0.3, 2}, {1, -0.3, 1}, {.5, -0.3, 1}}, {{.5, -1.5, 1}, {0, -1.5, 1}, {0, -1.5, 2}, {.5, -1.5, 2}, {1, -1.5, 2}, {1, -1.5, 1}, {.5, -1.5, 1}}};w = {{1, .5, .5, 1, .5, .5, 1}, {1, .5, .5, 1, .5, .5, 1}, {1, .5, .5, 1, .5, .5, 1}, {1, .5, .5, 1, .5, .5, 1}, {1, .5, .5, 1, .5, .5, 1}, {1, .5, .5, 1, .5, .5, 1}};
uk = {0, 0, 0, (1/4), (1/2), (3/4), 1, 1, 1};
vk = {0, 0, 0, (1/4), (1/2), (1/2), (3/4), 1, 1, 1};
Graphics3D[{
FaceForm[Yellow, Blue],
BSplineSurface[pts, SplineKnots -> {uk, vk}, SplineDegree -> 2, SplineWeights -> w, SplineClosed -> {False, True}]}]