zoukankan      html  css  js  c++  java
  • 【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/xiandedanteng/20180408_17guanglan.rar

    本作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>
  • 相关阅读:
    取模 分数取模 快速幂 费马小定理
    “科林明伦杯”哈尔滨理工大学第十届程序设计竞赛 部份签到题
    shell 脚本
    pyhcl语法
    数据库实验1 SQL
    杂七杂八 Ubuntu Linux
    Kattis, Kattis 的一些问题题解
    Meow Factor 【暴力】
    解决 Eclipse 项目有红感叹号的方法
    RuntimeException与CheckedException
  • 原文地址:https://www.cnblogs.com/heyang78/p/8742899.html
Copyright © 2011-2022 走看看