如何通过极坐标参数方程和SDF绘制出令人惊叹的复杂图案?
摘要:本文将介绍如何使用极坐标参数方程和上一篇文章提到的距离场SDF来绘制有趣的图案。有些曲线比起直角坐标系来说,更方便使用极坐标来表示,这个时候我们可以选择通过极坐标和直角坐标的相互转换,来实现图形的绘制
前言
本文将介绍如何使用极坐标参数方程和上一篇文章提到的距离场SDF来绘制有趣的图案。
说到曲线和几何图形的绘制,我们知道图形系统默认支持的是通过直角坐标绘制,但是有些曲线呢,不太容易使用直角坐标系来表示,却可以很方便地使用极坐标来表示,这个时候我们可以选择通过极坐标和直角坐标的相互转换,来实现图形的绘制。
下面我就用玫瑰线、花瓣线等曲线作为例子来进行演示。
在开始演示之前,我先简单介绍下极坐标和参数方程。
极坐标是使用相对极点的距离,以及与X轴正向的夹角,使用这一对值来表示平面上点的坐标。
参数方程表示的是点的坐标分别和相关参数的关系,所以通常会对应一个方程组,比如说二维平面上的点,会使用两个参数方程来表示。
我这里只是简单介绍一下,可能说的并不是很准确。我们也可以用圆作为例子,圆的标准方程大家都知道,假设圆心在原点,在直角坐标系下,圆的公式就是x的平方加上y的平方等于半径的平方,圆的参数方程是x等于半径乘以与X轴夹角的余弦值,y等于半径乘以与X轴夹角的正弦值。
\[\begin{cases}
x = r * cosθ \\
y = r * sinθ
\end{cases}
\]
但在极坐标系下,圆的参数方程就变成了r等于一个常量,θ等于与X轴的夹角。这基本上可以算是最简单的极坐标参数方程组了。
\[\begin{cases}
r = r \\
θ = t
\end{cases}
\]
那么基本的知识了解后,我们就可以开始使用极坐标参数方程来绘制图形和曲线了。
具体实现
现在就来演示通过曲线的极坐标参数方程来绘制曲线。
Canvas
首先先来看Canvas2D的例子,在Canvas中我们可以通过lineTo方法绘制足够多的线段将它们连在一起,来模拟曲线,所以我们可以通过参数方程获取足够多的点,将它们连接起来,这样就能最终完成曲线的绘制。
因此我们先来定义一个高阶函数parametric用于创建方程组,接收三个参数xFunc、yFunc和rFunc。xFunc和yFunc表示点的一对坐标值各自分别对应的参数方程,rFunc表示坐标映射函数。
export default function parametric(xFunc, yFunc, rFunc) {
return function(start, end, seg = 100, ...args) {
const points = [];
for (let i = 0; i <= seg; i ++) {
const p = i / seg;
// const t = start * (1 - p) + end * p;
const t = start + (end - start) * i / seg;
// console.log(t);
const x = xFunc(t, ...args);
const y = yFunc(t, ...args);
if (rFunc) points.push(rFunc(x, y));
else points.push([x, y]);
}
return {
draw: draw.bind(null, points),
points
}
}
}
这个高阶函数的返回值也是一个函数,在这个匿名函数应该不难理解,我简单说一下,它接收多个参数,必选的三个是坐标相关参数 t 的上下限start和end,以及要收集的点的数量seg,最终返回一个对象,这个对象带有一个draw方法,通过调用这个draw方法就可以完成曲线的绘制。
下面我们就通过parametric函数构造不同的曲线方程组。来看一个玫瑰线:
// 玫瑰线
const rose = parametric(
(t, a, k) => a * Math.cos(k * t), // r
t => t, // θ
fromPolar,
);
这里fromPolar是一种坐标映射函数,作用是将极坐标转换为直角坐标,这样我们才能在Canvas2d中使用坐标值。现在我们就可以通过调用rose函数,来获取曲线上的点并绘制曲线了。
