美妙的数学——绘制百度之星函数





一年一度的百度之星程序设计大赛又要开始了。今年的竞赛Logo用一颗星星来作为“百度之星”。这颗星星也很自然的成为了众参赛选手的关注焦点。这颗星星有一定的对称性,是不是可以用一个函数来构造出这颗星星的表达式呢?答案是肯定的。下面我们就来讨论如何用函数画出百度之星。

首先我们注意到星星的外部轮廓很接近一个倒置的正五边形,所以先思考如何绘制正五边形。我们考虑使用极坐标,借助数学软件Mathematica绘制函数。
如果以原点为中心,把坐标系按照极角划分成均匀的五份,那么每份应该是占72度角。对任意给定的极角,我们需要计算出它对应在哪个边上。我们将每个边的中点和坐标系原点相连,这样得到的五个边我们叫做轴。

1
f[t_] := Abs[t - (Floor[(t + Pi/10)/(Pi*2/5)]*Pi*2/5 + Pi/10)];

上述函数的参数为极角,得到的数值是这个极角到距离他最近的那个轴的夹角。构造方法从函数形式上应该容易思考出来。
有了这个夹角,我们容易算出极径的长度变化应当和余弦成反比,我们随意取定一个常数10,那么极径长度就是10/Cos[f[t]],因此我们可以画出极坐标图像,语句为:

1
PolarPlot[10/Cos[f[t]], {t, 0, 2*Pi}, PlotStyle -> {Red, Thick}]

图像为

注意到百度之星上面只有在极角取一部分值的时候,边正好和我们画的正五边形重合。一个很好的情况是,只有当极角靠近轴的时候,也即上面定义的f[t]很小的时候,那些边才应该画出来。所以我们需要另外定义一个函数g[t]来衡量f[t]是否比较小。

1
g[t_] := Floor[f[t]/(Pi/10)];

这里容易看出来,g[t]只可能取0或1,当极角t接近轴的时候,f[t]很小,则g[t]为0。而不考虑边界的情况下,f[t]不会超过36度角,所以g[t]最大也就是1。
我们先直接给出最后构造出的函数再慢慢解释。

1
h[r_, e_, t_] := r*((1 - g[t])/Cos[f[t]] + g[t]/Cos[Pi/10]*(Power[(Pi/10)/f[t], e]));

这里r控制百度之星的大小,e的作用后面解释,t仍然是极角。因为我们需要根据极角计算出极径,极角靠近轴的时候已经解决了,上述式子的前半部分(1 – g[t])/Cos[f[t]]用来绘制那些,对照前面可以看出它的含义。后半部分只有当f[t]比较大的时候g[t]才会取1,这部分也就会起作用。因为当极角在靠近和不靠近轴的临界点的时候,极径长度根据上述绘制的五边形可以知道是r/Cos[Pi/10],而极角远离轴的时候应当距离越远,极径就越短,来让边向内收缩。所以,需要乘以一个系数,由于刚好距离远的时候f[t]变大,所以只要取倒数就可以实现收缩。为保证比例,我们乘以(Pi/10)/f[t]即可。如果这样直接使用,星星会显得直上直下的,我们再用一个指数e来控制收缩速度。这样就得到了前面的式子。
我们可以用如下语句绘制这个图形,并隐藏掉坐标轴。

1
PolarPlot[h[10, 1.5, t], {t, 0, 2*Pi}, Axes -> None, PlotStyle -> {Red, Thick}]

上面选取了r=10,e=1.5,实际上也可以选取其他参数调整它的形状。绘制效果如图所示。

如果你愿意将函数f[t]和g[t]代入到h[r,e,t]中的话,就可以得到一个“百度之星函数”。当然了,本来看上去不复杂的函数,代入整理后会看上去很复杂,如果想吓唬人的话,可以用来晒晒。下面是代入整理后的式子。

我也给一个可以拷贝的式子,如果你有Mathematica的话,可以尝试绘制图像。

1
2
3
4
5
6
7
(1.85148 Floor[
   3.1831 Abs[-0.314159 + t - 1.25664 Floor[0.25 + 0.795775 t]]])/
 Abs[-(\[Pi]/10) + t - 2/5 \[Pi] Floor[1/4 + (5 t)/(2 \[Pi])]]^1.5 -
 10 (-1 + Floor[(
     10 Abs[-(\[Pi]/10) + t -
        2/5 \[Pi] Floor[1/4 + (5 t)/(2 \[Pi])]])/\[Pi]]) Sec[
   Abs[-(\[Pi]/10) + t - 2/5 \[Pi] Floor[1/4 + (5 t)/(2 \[Pi])]]]

本文同时发在百度贴吧中,欢迎顶帖支持:-)
http://tieba.baidu.com/f?kz=1088246529

本文来自Dora Blog,题目为美妙的数学——绘制百度之星函数,转载请注明出处。
如果你喜欢我的博客,请订阅本博客的RSS以更方便的阅读
欢迎关注我的新浪微博:http://weibo.com/diaorui1987