zoukankan      html  css  js  c++  java
  • JS画几何图形之五【过圆外一点作切线】

     样例:http://www.zhaojz.com.cn/demo/draw9.html

     依赖:【点】、【直线】、【圆】

    //画切线
    //point 圆外的一点
    //dot 圆心
    //r 半径
    function drawCircleTangent(point, dot, r){
        //画辅助线-start
        var color = 'DarkRed'; //切线的颜色
        var color2 = "#ccc"; //其它辅助线的颜色
        drawLine(dot, [dot[0]+9*r,dot[1]], {color: color2}); // 延长圆心所在的水平线
        drawLine(dot, [dot[0],dot[1]-4*r], {color: color2}); // 画出圆心所在的垂直线
        drawPoint({
            pw:2,ph:2,color:'DarkRed',point: [dot[0]+9*r,dot[1],'x']
        });
        drawPoint({
            pw:2,ph:2,color:'DarkRed',point: [dot[0],dot[1]-4*r,'y']
        });
        drawLine(point, [point[0],dot[1]], {color: color2}); // 画point到x轴的垂直线
        drawLine(point, dot, {color: color2}); // 连接point与dot
        drawLine([point[0]-2*r, point[1]], [point[0]+2*r, point[1]], {color: color2}); //画point所在的水平线
        //画辅助线-end
        //point.push('point');
        drawPoint({
            pw:2,ph:2,color:'DarkRed',point: point
        });
        //dot.push('centre');
        
        
        var r_square = Math.pow(r,2); // r的平方
        var point_v = point[1]-dot[1]; //point到x轴的距离的平方
        var point_h = point[0]-dot[0]; //point到y轴的距离的平方
        var c_square = Math.pow(point_v,2) + Math.pow(point_h,2); //point到圆心的距离的平方
        
        var c = Math.sqrt(c_square); //point到圆心的距离
        
        var sinA = Math.abs(point_v)/c; //sinA
        var cosA = Math.abs(point_h)/c; //cosA
        var b_square = c_square-r_square; //point到切点的距离的平方
        var b = Math.sqrt(b_square); //point到切点的距离
        
        var sinB = b/c; //sinB
        var cosB = r/c; //cosB
        //以圆心为坐标圆点,确定point所在的象限
        var quadrant  = 1; //默认值
        var pm_h = point_h == 0? point_h: point_h/Math.abs(point_h); //水平方向
        var pm_v = point_v == 0? point_v: point_v/Math.abs(point_v); //垂直方向
        var hv = pm_h*pm_v; //相乘,-1时point在一三象限,+1时point在二四象限,0时point在轴上
        switch(hv){
            case 1:
                if((pm_h+pm_v)==-2){ 
                    quadrant = 2; //第二象限
                }else{
                    quadrant = 4; //第四象限
                }
                break;
            case -1:
                if((pm_h-pm_v)==-2){
                    quadrant = 3; //第三象限
                }
                break;
            case 0:
                if((pm_h+pm_v)==-1){ //point在x轴的负半轴或者y轴的正半轴时,断定point在第二象限
                    quadrant = 2;
                }
                if((pm_h+pm_v)==1){ //point在x轴的正半轴或者y轴的负半轴时,断定point在第四象限
                    quadrant = 4;
                }
                break;
            default:
        }
        var sinC = 0;
        var conC = 0;
        var sinD = 0;
        var conD = 0;
        switch(quadrant){
            case 1:
                sinC = cosB*cosA+sinB*sinA; //sinC = sin(90+(B-A)) = cos(B-A) = cosB*cosA+sinB*sinA
                conC = -(sinB*cosA-cosB*sinA); //cosC = cos(90+(B-A)) = -sin(B-A) = -(sinB*cosA-cosB*sinA)
                sinD = -(cosA*cosB-sinA*sinB); //sinD = sin(270-(A+B))
                conD = -(sinA*cosB+cosA*sinB); //conD = cos(270-(A+B))
                break;
            case 2:
                sinC = -(cosB*cosA-sinB*sinA); //sinC = sin(-90+(A+B))
                conC = sinA*cosB+cosA*sinB; //conC = cos(-90+(A+B))
                sinD = cosA*cosB+sinA*sinB; //sinD = sin(90+(A-B))
                conD = -(sinA*cosB-cosA*sinB); //conD = cos(90+(A-B))
                break;
            case 3:
                sinC = -(cosA*cosB+sinA*sinB); //sinC = sin(-90+(A-B))
                conC = -(sinA*cosB-cosA*sinB); //conC = cos(-90+(A-B))
                sinD = (cosA*cosB-sinA*sinB);  
                conD = sinA*cosB+cosA*sinB;
                break;
            case 4:
                sinC = cosA*cosB-sinA*sinB;
                conC = -(sinA*cosB+cosA*sinB)
                sinD = -(cosA*cosB+sinA*sinB); //sinD = sin(270+(A-B))
                conD = (sinA*cosB-cosA*sinB); //conD = cos(270+(A-B))
                break;
            default:
        }
        
        var tangentPointA = [point[0]+b*conC, point[1]+b*sinC]; //切点A位置
        drawLine(point, tangentPointA, {color: color}); //画出切线
        drawLine(dot, tangentPointA, {color: color2}); //连接圆点与切点
        //drawArc(point, 17, (quadrant ==1 ||quadrant==4?180:0)-(quadrant ==2 ||quadrant==3?(-1):1)*Math.asin(sinC)*180/Math.PI, 0);
        
        var tangentPointB = [point[0]+b*conD, point[1]+b*sinD]; //切点B位置
        drawLine(point, tangentPointB, {color: color}); //画出切线
        drawLine(dot, tangentPointB, {color: color2}); //连接圆点与切点
        //drawArc(point, 27, (quadrant ==1 ||quadrant==4?180:0)-(quadrant ==2 ||quadrant==3?(-1):1)*Math.asin(sinD)*180/Math.PI, 0);
        
        drawPoint({ //描切点
            pw:3,ph:3,color:'DarkRed',point: tangentPointA
        });
        drawPoint({ //描切点
            pw:3,ph:3,color:'DarkRed',point: tangentPointB
        });
        //画辅助弧
        //(quadrant ==1 ||quadrant==4?360:0)
        drawArc(point, b, 60, (quadrant ==1 ||quadrant==4?180:0)-(quadrant ==2 ||quadrant==3?(-1):1)*Math.asin(sinC)*180/Math.PI-5);
    }
  • 相关阅读:
    第3课 线性分类器损失函数与最优化
    李飞飞机器视觉课程笔记:第2课 K最近邻与线性分类器
    周志华《机器学习》第二章学习笔记
    通过anaconda安装tensorflow
    周志华《机器学习》第一章学习笔记 奥卡姆剃刀原理、没有免费的午餐定理(NFL)、回归模型
    DPM目标检测模型
    损失函数的理解
    mini-batch的理解
    前向传播、后向传播
    SVM(支持向量机)的理解
  • 原文地址:https://www.cnblogs.com/zhaojz/p/4218026.html
Copyright © 2011-2022 走看看