圣诞树彩灯曲线方程

马上就要圣诞节了,圣诞树上会绕一圈彩灯,以表对圣诞节的敬意,淦!讨论一下理想状态下圣诞树彩灯曲线方程。

对于一个圣诞树,绕的一圈的彩灯的曲线是什么样的呢?侧面看起来是什么样的?如果彩灯曲线上彩灯分布式均匀的,那么彩灯的位置该怎么计算?

本文假设圣诞树是一个圆锥体,彩灯从顶端开始等梯度绕线,并绕了整数圈,如下图所示:

圆锥体绕线示意图

本文主要固定值:

  • H:圆锥体高
  • W:圆锥体底面直径
  • A:圆锥顶点
  • O:圆锥底面圆心
  • M:绕线与底面的交点
  • Q:绕线的圈数
  • T:彩灯的间隔距离

一、建立三维的彩灯曲线方程

以圆锥的底面圆心O为基准,在底面上建立极坐标系;以从圆锥顶点A到圆锥底面圆心O方向为$Z$轴;建立坐标系,如下图所示

建立三维的彩灯曲线方程

绕线的圈数是Q,所以绕线的总角度是 $2{\pi}Q$,由于绕线是均匀的,所以$Z$轴方向的$h$和极坐标平面上的曲线半径$l$都是均匀变化的,所以曲线方程如下:

$$f(\theta, l, h)
\begin{cases}
\theta=\theta , &0 \le \theta \le 2{\pi}Q \
l = { {W\theta}\over{4{\pi}Q} }, \
h = { {H\theta}\over{2{\pi}Q} },
\end{cases}$$

其中:

曲线半径最大是$W\over2$,在$\theta \in[0, 2{\pi}Q]$的范围内均匀变化所以$l = { { W\over2 }\over{2{\pi}Q} }\theta = { {W\theta}\over{4{\pi}Q} }$

圆锥高为$H$,在$\theta \in[0, 2{\pi}Q]$的范围内均匀变化所以$l = { { H }\over{2{\pi}Q} }\theta = { {H\theta}\over{2{\pi}Q} }$

二、俯视图的彩灯曲线

圣诞树上彩灯从树的俯视图方向看如下:

俯视图的彩灯曲线

为什么俯视图(像)是螺旋线呢?俯视图去掉了三维视图中高的特征,所以可以在俯视图上建立极坐标系,如下如所示:

俯视图上建立极坐标系

从三维坐标系中抽出极坐标平面相关的变量,由于三维坐标系中的曲线方程$f(\theta, l, h)$组成的方程中与极坐标平面相关的变量$\theta,l$与$h$没有关系,所以俯视图彩灯曲线方程如下:

$$l = f(\theta) = { {W\theta}\over{4{\pi}Q} } \ \ \ \ \ \ \ 0 \le \theta \le 2{\pi}Q \$$

其中:

$l$是随$\theta$均匀变化的,所以俯视图是平面上的螺旋线。

三、主视图的彩灯曲线

圣诞树上的彩灯从树的主视图方向看如下:

主视图的彩灯曲线

主视图为什么长这个样子呢?主视图上关于三维坐标系中的$h$相关的特征是没有损失的,那么关于螺旋线在主视图上的投影是什么样的呢?

我们可以在俯视图的螺旋线上看(如下图所示),我们对于螺旋线的任何一个位置,向极坐标的起始位置作垂线(起始位置是与主视图方向平行的),也就是在$\theta$处,我们在主视图方向看到的偏离圆锥中轴线方向的长度是$l*cos(\theta)$。

我们在主视图上建立如下坐标系:

主视图上建立坐标系

所以根据以上的分析,在$h$方向是随$\theta$均匀变化的,在$w$方向,坐标长度是$l*cos(\theta)$,但是在主视图的坐标系中不存在$\theta$变量,所以我们使用h变量来替换掉$\theta$,根据彩灯的三维曲线方程,我们知道$h = { {H\theta}\over{2{\pi}Q} }$,所以$\theta$使用$h$来表示则是$\theta = { {2{\pi}Qh}\over{H} }$,$l$使用$\theta$替换可得$l = { {W\theta}\over{4{\pi}Q} }$。所以在$w$方向,$w = l\ cos(\theta) = { {W\theta}\over{4{\pi}Q} } \ cos(\theta) = {Wh\over2H}\ cos({ {2{\pi}Qh}\over{H} })$ 。所以主视图上的方程如下:

$$w = f(h) = {Wh\over2H}\ cos({ {2{\pi}Qh}\over{H} }) \ \ \ \ \ \ \ 0 \le h \le H \$$

其中:

$w$的核心为$h \ cos(h)$,该函数是一次函数$h$和三角函数$cos(h)$的乘积,即使用一次函数$h$对三角函数$cos(h)$的范围进行了限制。

四、主视图上彩灯位置方程

俯视图上来看彩灯的间隔距离是不相等的(由于俯视图上将曲线等梯度下降这一特性抹掉了,彩灯实际的距离应该是$\sqrt{ 彩灯间隔对应梯度^2 + 俯视图彩灯间隔^2 }$,联想到小时候见到的一个三角形纸片卷在铅笔上从而类似盘山公路,将螺旋线展开可能也是一个直角三角形,将盘山公路这一想法对应到螺旋线中,从三维方程中可知,$h = { {H \theta}\over{2{\pi}Q} } $,即$h$是随着$\theta$线性变化的,即盘上公路展开的图形的高是随着$\theta$线性变化的;盘山公路展开的图形对应的底边是$l\Delta \theta$的和式,由于$l = { {W\theta}\over{4{\pi}Q} }$,所以底边对应增量$d{v} = { {W\theta}\over{4{\pi}Q} } d*{\theta}$,求积分得$V = { {W\theta^{2} }\over{8{\pi}Q} } $,所以展开图形的底边不是随着$\theta$线性变化的,所以螺旋线展开不是一个直角三角形,其中斜边向下弯曲,因为斜率随着$\theta$的增大而减小)

但我们为了简化计算,认为螺旋线的展开是一个三角形,并且从$\theta$的范围得出底边的总长度是${\pi wQ}\over{2}$。

为了计算彩灯间隔T对应的$\Delta h$,有了$\Delta h$才能计算每一个彩灯相对于上一个$h$位置的$w$值。

假设彩灯在俯视图上的间隔是T,假设间隔T对应的角度变化量为$\Delta \theta$,所以T和$\Delta \theta$的对应关系是

$$T = l\Delta \theta = { {W\theta}\over{4{\pi}Q} } \Delta \theta$$

代入$\theta = { {2{\pi}Qh}\over{H} }$可得

$$\Delta \theta = { 4{ {\pi}QT}\over{W\theta} } = { 2HT \over { Wh } }$$

由$\theta = { {2{\pi}Qh}\over{H} }$可得

$$\Delta \theta = { {2{\pi}Q\Delta h}\over{H} }$$

联立方程(5)(6)消去$\Delta \theta$可得

$$\Delta h = { TH^2 \over {\pi WQh} }$$

所以每一次彩灯的变化量与当前的h值有关(假设当前为$h$,则下一次位置是$h + \Delta h$,以此自以为是的将方程7进行修正,将$h$值取为当前$h$和下一次位置$h + \Delta h$的平均值$h + { \Delta h \over 2 }$,从而得到如下方程)

$$\Delta h = { TH^2 \over {\pi WQ(h + {\Delta h\over2}) } }$$

从而得到一元二次方程

$${\pi WQ \over 2}·\Delta h^2 + {\pi WQh}·\Delta h - TH^2 = 0$$

由$x_1,x_2 = {-b \pm \sqrt{b^2-4ac} \over 2 }$得

$$\Delta h_1 = -h + { \sqrt{ h^2 + {2TH^2\over{ \pi WQ } } } }
\
\Delta h_2 = -h - { \sqrt{ h^2 + {2TH^2\over{ \pi WQ } } } } (负值舍去)$$

JS语言代码示例

text
1
2
3
4
5
6
7
8
9
10
11
12
13
14

var h_start = 0.001;
var h_max = 300;
for(double h = h_start; h < h_max;){
   // 计算灯位置的x坐标和y坐标
   var light_x = h;
   var light_y = (W*h)/(2*H) * Math.sin(2*Math.PI*Q*h/H)

   // 更新h的值
   var equation_A = Math.PI * W * Q / 2;
   var equation_B =  Math.PI * W * Q * h;
   var equation_C = -(T * H * H);
   h = Math.sqrt(equation_B * equation_B - 4 * equation_A * equation_C) / (2 * equation_A);
}

渲染出来的图:

渲染出来的图

备注:

如果想固定彩灯的总数$N$,需要求得彩灯间隔T的值,俯视图上的线的总长度是${\pi wQ}\over{2}$,所以该长度除以$N$得$T = { {\pi wQ}\over{2N} } $ 。