【Canvas】动态正17边光阑 向高斯致敬

【背景知识】

公元前三世纪,欧几里得在《几何原本》中记载了正方形,正五边形,正六边形的做法,后来人们也掌握了正十五边形作图,但之后两千多年,人们没有在更高阶边形上取得突破。

1796年,19岁的高斯证明了正17边形可以由尺规作图作出,但没有给出具体做法;

1825年Johanes Erchinger发表了第一个正十七边形尺规作图法;

1898年,高斯的孙子发现了高斯在1796年3月30日关于正17边形作图的手稿,可以推断,高斯至少在当时在草稿纸上完成了作图分析过程。

1832年,里奇罗特发表了正257边形尺规作图法,手稿长达80页。

1894年,德国数学家Johann Gustav Hermes发表了正65537边形尺规作图法,这是目前人类最复杂的尺规作图,手稿保存在德国哥廷根大学。

 

我用canvas制作了正十七边形光阑,此种类型光阑多用于显微镜采光口。借此向伟大数学家高斯致敬。

代码没有经过大改变,只是在 http://www.cnblogs.com/xiandedanteng/p/8735444.html 的基础上把angleCount改成了17,另外优化了getColor函数。

效果见下面五个图形,想看动画效果请自行下载代码然后用chrome浏览器打开。或者从 https://files.cnblogs.com/files/xiandedanteng/17%E5%85%89%E9%98%91.rar 下载录像观看。

代码下载地址:https://files.cnblogs.com/files/heyang78/iris-aperture-master.zip

本作Github url:https://github.com/horn19782016/iris-aperture

代码如下:

<!DOCTYPE html>
<html lang="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<head>
     <title>17角光阑 2018年4月8日 向高斯致敬</title>
    </head>

     <body onload="draw()">
        <canvas id="myCanvus" width="400px" height="400px" style="border:1px dashed black;">
            出现文字表示你的浏览器不支持HTML5
        </canvas>
     </body>
</html>
<script type="text/javascript">
<!--
function draw(){
    var canvas=document.getElementById('myCanvus');    
    canvas.width=400;
    canvas.height=400;    

    context=canvas.getContext('2d');    
    context.translate(200,200);

    slot=new Slot();
    animate();
};

var delta=0;    // 旋转角
var radius=0;    // 旋转半径
var outerRad=200;// 外径
var context;    // 绘画上下文
var slot;        // 光阑对象
var angleCount=17;// 三角光阑为3,四角光阑为4,六角光阑为6

function animate(){    
    context.clearRect(-200,-200,400,400);// 清屏
    
    slot.update(radius,delta,outerRad);
    slot.paintBg(context);
    slot.paint(context);
    slot.paintBase(context);
        
    delta+=0.5;
    radius+=1;

    if(radius<outerRad*0.9){        
        window.requestAnimationFrame(animate);// 让浏览器自行决定帧速率
    }
}

function Slot(){
    var obj=new Object;

    obj.ax=0;
    obj.ay=0;
    obj.bx=0;
    obj.by=0;
    obj.cx=0;
    obj.cy=0;
    obj.angleA=0;
    obj.angleB=0;
    obj.angleC=0;
    obj.radius=0;
    obj.outerRad=0;
    obj.img=new Image();
    obj.img.src="earth.jpg";    

    // 计算
    obj.update=function(radius,theta,outerRad){
        this.radius=radius;
        this.outerRad=outerRad;        

        var alpha=Math.acos(radius/outerRad);
        this.angleA=getRad(theta)+alpha;
        this.ax=outerRad*Math.cos(this.angleA);
        this.ay=outerRad*Math.sin(this.angleA);

        var R=radius/Math.cos(Math.PI/angleCount);
        this.angleB=getRad(theta)-Math.PI/angleCount;
        
        this.bx=R*Math.cos(this.angleB);
        this.by=R*Math.sin(this.angleB);

        this.angleC=this.angleA-2*Math.PI/angleCount;
        this.cx=outerRad*Math.cos(this.angleC);
        this.cy=outerRad*Math.sin(this.angleC);
    };

    // 画背景
    obj.paintBg=function(ctx){
        context.drawImage(this.img,0,0,800,800,-200,-200,400,400);
    };

    // 描光阑
    obj.paint=function(ctx){

        for(var i=0;i<angleCount;i++){
            ctx.save();

            ctx.fillStyle = getColor(i % 9);
            ctx.rotate(2*Math.PI/angleCount*i);

            ctx.beginPath();
            ctx.moveTo(this.ax,this.ay);
            ctx.lineTo(this.bx,this.by);
            ctx.lineTo(this.cx,this.cy);
            ctx.arc(0,0,this.outerRad,this.angleC,this.angleA,false);
            ctx.closePath();
            ctx.fill();

            ctx.restore();
        }
    };

    // 描基座
    obj.paintBase=function(ctx){
        ctx.strokeStyle = "black";

        for(var i=0;i<4;i++){
            ctx.save();
            ctx.fillStyle = getColor(13);
            ctx.rotate(Math.PI/2*i);

            ctx.beginPath();
            
            ctx.arc(0,0,this.outerRad,0,Math.PI/2,false);
            ctx.lineTo(this.outerRad,this.outerRad);
            ctx.lineTo(this.outerRad,0);

            ctx.closePath();
            ctx.fill();

            ctx.restore();
        }
    };

    return obj;
}

// 角度得到弧度
function getRad(degree){
    return degree/180*Math.PI;
}

// 得到颜色
function getColor(index){
    var arr=["green","silver","lime","gray",
             "white","yellow","maroon","navy",
             "red","blue","purple","teal","fuchsia",
             "aqua","black"];

    if(index>arr.length){
        index=index % arr.length;
    }

    return arr[index];
}

//-->
</script>

 

posted @ 2018-04-08 09:08  逆火狂飙  阅读(500)  评论(2编辑  收藏  举报
生当作人杰 死亦为鬼雄 至今思项羽 不肯过江东