最近有个小问题,已知三个点坐标,及其半径大小,求其三个圆相交的中心点。
利用各相交线段组成的三角形重心找出其中心点。
代码如下:
<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画布技术写的,里面包含画点、画线、画圆等知识点,自己做个标记。
这篇博客介绍了如何使用JavaScript解决已知三个圆的坐标和半径,找到它们相交中心点的问题。通过三角形重心法,实现了点击画布添加点、计算圆相交和画出相交线段,最后找出中心点的功能。涉及到的技术包括canvas画布、事件监听、坐标转换和几何计算。
3802

被折叠的 条评论
为什么被折叠?



