js 三点定位中心点问题

这篇博客介绍了如何使用JavaScript解决已知三个圆的坐标和半径,找到它们相交中心点的问题。通过三角形重心法,实现了点击画布添加点、计算圆相交和画出相交线段,最后找出中心点的功能。涉及到的技术包括canvas画布、事件监听、坐标转换和几何计算。

最近有个小问题,已知三个点坐标,及其半径大小,求其三个圆相交的中心点。

利用各相交线段组成的三角形重心找出其中心点。

代码如下:

<div class="" align="center"style="position: absolute; z-index: 1; top: 250px; left: 100px;">    
        <canvas id="myCanvas" style="border: 1px solid #000000;" height="300px" width="600px">    
        </canvas>
</div>
        
 <div class=""align="left"style="position: absolute; z-index: 1; top: 30px; left: 100px;">    
          A点的距离:<input type="text" id="input_a" value="" />  
          B点的距离:<input type="text" id="input_b" value="" />  

          C点的距离:<input type="text" id="input_c" value="" /> <br /><br />

          <button id="but_draw" onclick="drawCircle()">画圆</button>

         <button id="but_clear" onclick="clearC()">清除</button>

</div>

<script type="text/javascript">
    
        var points=[];
          function windowTocanvas(canvas, x, y) {
                var bbox = canvas.getBoundingClientRect();
                return {
                    x: x - bbox.left * (canvas.width / bbox.width),
                    y: y - bbox.top * (canvas.height / bbox.height)
                };

            }
         window.onload=function(){
            var canvas=document.getElementById("myCanvas");
            var ctx = canvas.getContext('2d');
            canvas.onclick=function(event){
            if(points.length>=3)
            {
                alert("只能画三个点坐标。");
                return;
            }
                        
            var loc=windowTocanvas(canvas,event.clientX,event.clientY);
                var x=parseInt(loc.x);
                var y=parseInt(loc.y);
            
                var pointName;
                if(points.length=="0")
                {
                    pointName="A";
                }
                else if(points.length=="1")
                {
                    pointName="B";
                }else
                {
                    pointName="C";
                }
                points.push({"id":pointName,"x":x,"y":y,"r":"0"});
            
                ctx.beginPath();//画实心圆
                ctx.arc(x,y,3,0,2*Math.PI,true);
                ctx.closePath();
                ctx.fillStyle="red";
                ctx.fill();
                //写字
                ctx.fillStyle = "#000000";//颜色
                ctx.font = "normal 20px 微软雅黑";//字体
                ctx.textBaseline = "middle";//竖直对齐
                ctx.textAlign = "center";//水平对齐 
                ctx.fillText(pointName, x+15, y, 20);//绘制文字
                
            }
        };
        
        function drawPoint_Text(x,y,pointName)
        {
            console.log("画点:"+x+";"+y+";"+pointName);
            var canvas=document.getElementById("myCanvas");
            var ctx = canvas.getContext('2d');
            ctx.beginPath();//画实心圆
            ctx.arc(x,y,3,0,2*Math.PI,true);
            ctx.closePath();
            ctx.fillStyle="red";
            ctx.fill();
            //写字
            ctx.fillStyle = "#000000";//颜色
            ctx.font = "normal 20px 微软雅黑";//字体
            ctx.textBaseline = "middle";//竖直对齐
            ctx.textAlign = "center";//水平对齐 
            ctx.fillText(pointName, x+15, y, 20);//绘制文字
        }
        
        function drawCircle()
        {
            if(points.length!=3)
            {
                alert("需要在下图中首先画三个点。");
                return;
            }
            
            var Ra=document.getElementById("input_a").value;
            var Rb=document.getElementById("input_b").value;
            var Rc=document.getElementById("input_c").value;
            
            if(Ra==''||Ra==' '||Rb==''||Rb==' '||Rc==''||Rc==' ')
            {
                alert("半径值不能为空。");
                return;
            }
            var canvas=document.getElementById("myCanvas");
            var cxt=canvas.getContext("2d");
            //先清空画板,避免多次重复画点及圆圈
            cxt.clearRect(0,0,canvas.width,canvas.height);
            if(centerPoints.length>0)
            {
                centerPoints.splice(0,centerPoints.length);
            }
            //画点
            
             //画一个空心圆
            for(var i = 0,point;point = points[i]; i++){
                var cx=point.x;
                var cy=point.y;
                var cR;
                var pointName;
                if(point.id=='A')
                {pointName="A";
                    cR=Ra;
                    point.r=Ra;
                }else if(point.id=='B')
                {pointName="B";
                    cR=Rb;
                    point.r=Rb;
                }else{
                pointName="C";
                    cR=Rc;
                    point.r=Rc;
                }
                drawPoint_Text(cx,cy,pointName);//画点
                cxt.beginPath();
                cxt.arc(cx,cy,cR,0,360,false);
                cxt.lineWidth=3;
                cxt.strokeStyle="green";
                cxt.stroke();//画空心圆
                cxt.closePath();
            }
            P2PL();            
            
        };
        
        var centerPoints=[];
        //找圆相交点,画直线,并求线段中心点坐标
        function P2PL()
        {
            var info="";
            for(var i = 0,point;point = points[i]; i++){
                if(i<points.length-1)
                {
                    info +=juli(point.id,point.x,point.y,point.r,points[i+1].id,points[i+1].x,points[i+1].y,points[i+1].r);
                    
                    CirIntersect(point.id,point.x,point.y,point.r,points[i+1].id,points[i+1].x,points[i+1].y,points[i+1].r);
                }else{
                    info +=juli(point.id,point.x,point.y,point.r,points[i-2].id,points[i-2].x,points[i-2].y,points[i-2].r);
                    
                    CirIntersect(point.id,point.x,point.y,point.r,points[i-2].id,points[i-2].x,points[i-2].y,points[i-2].r);
                }
            }
        
            if(centerPoints.length==3)
            {
                var x1,y1,x2,y2,x3,y3;
                //for(var j = 0,cpoint;cpoint = centerPoints[j]; //j++){                }
                x1=centerPoints[0].Xc;
                y1=centerPoints[0].Yc;
                x2=centerPoints[1].Xc;
                y2=centerPoints[1].Yc;
                x3=centerPoints[2].Xc;
                y3=centerPoints[2].Yc;
                drawLine(x1,y1,x2,y2,"#000000");
                drawLine(x1,y1,x3,y3,"#000000");
                drawLine(x2,y2,x3,y3,"#000000");
                //求三角形重心心点位置
                var CX=(x1+x2+x3)/3;
                var CY=(y1+y2+y3)/3;
                drawPoint(CX,CY);
                console.log("最终点的位置为:X--"+CX+", Y--"+CY);            
            }
        }
        
        function juli(n1,x1,y1,r1,n2,x2,y2,r2) {       
            //var x1;   // 第一个点的横坐标
            //var y1;   // 第一个点的纵坐标
            //var x2;   // 第二个点的横坐标
            //var y2;   // 第二个点的纵坐标
            var xdiff = x2 - x1;// 计算两个点的横坐标之差
            var ydiff = y2 - y1;// 计算两个点的纵坐标之差
            var diff = Math.pow((xdiff * xdiff + ydiff * ydiff), 0.5);   // 计算两点之间的距离,并将结果返回表单元素
            var info;
            var dis=Number(r1)+Number(r2);
            if(diff > dis)
            {
              info=n1+"与"+n2+"两个圆不相交,两圆心距离:";
            }else if(diff==dis)
            {
                info=n1+"与"+n2+"两个圆相切,两圆心距离:";
            }else{
                info=n1+"与"+n2+"两个圆相交,两圆心距离:";
            }
            console.log(info+diff+";  半径和:"+dis);
            return info+diff+";  ";
        }
        
        function CirIntersect(n1,x1,y1,r1,n2,x2,y2,r2){
            var a,b,c;// 在一元二次方程中 a*x^2+b*x+c=0
            //x的两个根 x_1 , x_2
            //y的两个根 y_1 , y_2
            var x_1,x_2,y_1,y_2;
            //判别式的值
            //double delta = -1;
            var delta= Number(-1);
            //如果 y1!=y2
            if(y1!=y2){

                //为了方便代入
                var A = (x1*x1 - x2*x2 +y1*y1 - y2*y2 + r2*r2 - r1*r1)/(2*(y1-y2));
                var B = (x1-x2)/(y1-y2);

                a = 1 + B * B;
                b = -2 * (x1 + (A-y1)*B);
                c = x1*x1 + (A-y1)*(A-y1) - r1*r1;

                //下面使用判定式 判断是否有解    
                delta=b*b-4*a*c;

                if(delta >0)
                {

                    x_1=(-b+Math.sqrt(b*b-4*a*c))/(2*a);
                    x_2=(-b-Math.sqrt(b*b-4*a*c))/(2*a);
                    y_1 = A - B*x_1;
                    y_2 = A - B*x_2;
                }
                else if(delta ==0)
                {
                    x_1 = x_2 = -b/(2*a);
                    y_1 = y_2 = A - B*x_1;
                }else
                {
                    console.log("圆"+n1+"圆"+n2+"两个圆不相交");
                    return null;
                }
            }
            else if(x1!=x2){

                //当y1=y2时,x的两个解相等
                x_1 = x_2 = (x1*x1 - x2*x2 + r2*r2 - r1*r1)/(2*(x1-x2));

                a = 1 ;
                b = -2*y1;
                c = y1*y1 - r1*r1 + (x_1-x1)*(x_1-x1);

                delta=b*b-4*a*c;

                if(delta >0)
                {
                    y_1 = (-b+Math.sqrt(b*b-4*a*c))/(2*a);
                    y_2 = (-b-Math.sqrt(b*b-4*a*c))/(2*a);
                }
                else if(delta ==0)
                {
                    y_1=y_2=-b/(2*a);
                }else
                {
                    console.log("圆"+n1+"圆"+n2+"两个圆不相交;");
                    return null;
                }
            }
            else
            {
                console.log("圆"+n1+"圆"+n2+"无解;");
                return null;
            }
            console.log("圆"+n1+"圆"+n2+"的交点坐标:("+x_1+","+y_1+"),("+x_2+","+y_2+")");
            drawLine(x_1,y_1,x_2,y_2,"#FF0000");
            drawCenterPoint(x_1,y_1,x_2,y_2);
    };
    
    function drawLine(x1,y1,x2,y2,colors){
        var canvas=document.getElementById("myCanvas");
        var ctx = canvas.getContext('2d');
        //设置线条宽度  
        ctx.lineWidth = "1";  
        //起始一条路径,或重置当前路径  
        ctx.beginPath();  
        //设置画笔颜色  
        ctx.strokeStyle=colors;  
        //把路径移动到画布中的指定点,不创建线条  
        ctx.moveTo(x1,y1);  
        //添加一个新点,然后在画布中创建从该点到最后指定点的线条  
        ctx.lineTo(x2,y2);  
        //创建从当前点回到起始点的路径  
        ctx.closePath();  
        //绘制已定义的路径  
        ctx.stroke();
    }
    //相交线段求中心点位置
    function drawCenterPoint(x1,y1,x2,y2){
        var x,y;
        x=(x1+x2)/2;
        y=(y1+y2)/2;
        console.log("线段中心点:"+x+", "+y);
        centerPoints.push({"Xc":x,"Yc":y});
        
        var canvas=document.getElementById("myCanvas");
        var ctx = canvas.getContext('2d');
        ctx.beginPath();//画实心圆
        ctx.arc(x,y,2,0,2*Math.PI,true);
        ctx.closePath();
        ctx.fillStyle="black";
        ctx.fill();        
    };
    //求三角形重心心点位置
    function drawPoint(x,y){        
        var canvas=document.getElementById("myCanvas");
        var ctx = canvas.getContext('2d');
        ctx.beginPath();//画实心圆
        ctx.arc(x,y,5,0,2*Math.PI,true);
        ctx.closePath();
        ctx.fillStyle="black";
        ctx.fill();        
    };
    
    function clearC()
    {
        console.log("开始清除动作");
        document.getElementById("input_a").value="";
        document.getElementById("input_b").value="";
        document.getElementById("input_c").value="";
        console.log("点集合长度:"+points.length);
        if(points.length>0)
        {
            points.splice(0,points.length);
        }
        if(centerPoints.length>0)
        {
            centerPoints.splice(0,centerPoints.length);
        }
        
        var c=document.getElementById("myCanvas");  
        var cxt=c.getContext("2d");  
        cxt.clearRect(0,0,c.width,c.height);
    };
        
</script>

PS:第一次写,当然代码中有很多重复的东西,也是一次学习,也参考了很多网上的知识点,利用canvas画布技术写的,里面包含画点、画线、画圆等知识点,自己做个标记。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值