参考:
表达式:直线方程的各种表达式
中垂线的计算方法: 线段中垂线解析式公式
两直线求交点的方法:一种计算两直线交点的方法(灵歌1992的博客)
这两篇写的很足够了,我用Js来写写代码,顺便可以添加这个新功能到上一篇 从图片测长度 的博客里面;
很多相当有趣的功能,仅仅只会用到高中的知识,所以复习是挺必要的一件事,而且自从毕业以后,要让我手工计算点什么东西,心底里总有些害怕,不知道该从何处入手,复习应该可以拾回年轻时的自信吧,就算只是写写推导过程,应该也是有益的,所以想到什么就复习什么吧,而且再学一遍,很可能会有新的体会。
直线方程
这里面见得最多、最熟悉的直线方程表达式是所谓的: 斜截式:
如果有两个点,就可以直接得到斜率,然后将斜率和p1坐标,带入直线方程求出截距:
可以看出,这两个参数还是比较复杂的,但是可以看到,它们的分母是一样的,所以代入斜截式的方程式,
消掉分母:
移 项:
定 义:
然后就可以得到直线方程的一般式了:
求得的 ABC 一般会有一个公约数,但是在此不考虑实际的约分情况,毕竟不是要考试,有个公约数,直线也还是那个直线。
可以看出这个一般式长得很像线性代数里的东西,而且根据参考的文章,这个的确比较好用。
求中垂线的方程
当前直线的法向量为 由此可求出垂直线的一般方程:
已知 以及将其所经过的点 代入,求取
得:
求中垂线的交点
设交点为 按照以上方法求出两条线的中垂线一般方程 和
联立这两个方程即可,得到
提出公共的分母 单独计算出一个值,即可形成程序。
当 D=0 时需要特殊对待,此时两条直线平行,没有相交线,也就不用求圆心了。
可知,中垂线的交点即为三点圆的圆心。
先把程序效果放出来
我是以轮距为参考,绘制了一个三点圆,可见计算出来的数据是比较符合的。
程序代码:
function circleCenter(ctx){
var Coef1 = nline(thePoint[0],thePoint[1])
var Coef2 = nline(thePoint[1],thePoint[2])
var D = Coef1[0]*Coef2[1] - Coef1[1]*Coef2[0]
if(D != 0){
var ox = (Coef1[2]*Coef2[0] - Coef2[2]*Coef1[0])/D;
var oy = (Coef1[2]*Coef2[1] - Coef2[2]*Coef1[1])/D;
thePoint[3] = {
X: ox,
Y: oy,
R:((thePoint[0].X-ox)**2+(thePoint[0].Y-oy)**2)**(1/2)
};
ctx.beginPath();
ctx.arc(thePoint[3].X, thePoint[3].Y, thePoint[3].R, 0, Math.PI*2);
ctx.moveTo(thePoint[3].X, thePoint[3].Y);
ctx.lineTo(thePoint[2].X, thePoint[2].Y)
ctx.fillText("半径:"+thePoint[3].R*scale+"mm",10,50,200);
ctx.stroke();//绘制
}
}
function nline(p1,p2){
var A = p2.Y-p1.Y;
var B = p1.X-p2.X;
var Cv = (A*(p1.Y +p2.Y)-B*(p1.X +p2.X))/2; //垂直平分线的
return [A,B,Cv];
}
把这个加进去,再稍微修改一下之前的代码
将,oc.onmousedown 函数里的完成标志添加限制,等于是修改了模式。当然,在这之前要先加一个画圆模式的变量
if(!CircleMode){CalCompleted = true;}
然后,添加测量距离里的第三个点的处理,
else if(CircleMode && circleNum == 3){
circleCenter(ctx);
CalCompleted = true;
}
然后就可以开心的测量半径了。