功能:已知平面圆弧上两点坐标及圆半径,计算圆心坐标.
编程语言:JavaScript
分析:
给定圆弧半径,经过平面上两点的圆弧圆心落在两点的中垂线上, 一般有两个.
算法:
1) 计算两点之间的中点坐标.
2)计算连接两点的方向向量.
3)将两点方向向量顺时针旋转90度,得到中垂线方向向量.
4)单位化中垂线方向向量.
5)计算中点与圆心的偏移距离.
6)将中点沿中垂线方向移动偏移距离,既得到第一个圆心坐标.
7)将中垂线方向旋转180度(也就是将两点方向向量逆时针旋转90度),重复步骤6,得到第二个圆心坐标.
// // 由平面圆弧上两点坐标及圆半径,计算圆心坐标的JavaScript脚本代码 // Author: Chunfeng Yang // Date: April 1st, 2018 // // Data Structure // function Point( x, y) { this.x = x; this.y = y; if( (typeof(x) == "undefined") || (typeof(y) == "undefined") ){ this.x = 0; this.y = 0; } this.distance = function( otherPoint ) { var self = this; if (typeof(otherPoint) == "undefined") { return ; // The return obejct is undefined. } if( (typeof(self.x) == "undefined") || (typeof(self.y) == "undefined") ){ return; } if( (typeof(otherPoint.x) == "undefined") || (typeof(otherPoint.y) == "undefined") ){ return; } var dx = parseFloat(self.x) - parseFloat(otherPoint.x); var dy = parseFloat(self.y) - parseFloat(otherPoint.y); return ( Math.sqrt( parseFloat(dx) * parseFloat(dx) + parseFloat(dy) * parseFloat(dy) ) ); } this.middle = function( otherPoint ) { var self = this; if (typeof(otherPoint) == "undefined") { return ; // The return obejct is undefined. } if( (typeof(self.x) == "undefined") || (typeof(self.y) == "undefined") ){ return; } if( (typeof(otherPoint.x) == "undefined") || (typeof(otherPoint.y) == "undefined") ){ return; } var thex = ( parseFloat(self.x) + parseFloat(otherPoint.x) ) / 2.0; var they = ( parseFloat(self.y) + parseFloat(otherPoint.y) ) / 2.0; return ( new Point( thex, they ) ); } this.vector = function( otherPoint ) { var self = this; if (typeof(otherPoint) == "undefined") { return ; // The return obejct is undefined. } if( (typeof(self.x) == "undefined") || (typeof(self.y) == "undefined") ){ return; } if( (typeof(otherPoint.x) == "undefined") || (typeof(otherPoint.y) == "undefined") ){ return; } var dx = parseFloat(otherPoint.x) - parseFloat(self.x); var dy = parseFloat(otherPoint.y) - parseFloat(self.y); return ( new Point( dx, dy ) ); } this.moveto = function( theVector ) { var self = this; if (typeof(theVector) == "undefined") { return ; // The return obejct is undefined. } if( (typeof(self.x) == "undefined") || (typeof(self.y) == "undefined") ){ return; } if( (typeof(theVector.x) == "undefined") || (typeof(theVector.y) == "undefined") ){ return; } var thex = parseFloat(theVector.x) + parseFloat(self.x); var they = parseFloat(theVector.y) + parseFloat(self.y); return ( new Point( thex, they ) ); } } function calCircleCenter( p1, p2, r ) { // Checking parameters if (typeof(p1) == "undefined") { console.error("Parameter point 1 is undefined"); return; } if (typeof(p2) == "undefined") { console.error("Parameter point 2 is undefined"); return; } if (typeof(r) == "undefined") { console.error("Parameter radius is undefined"); return; } if( parseFloat(r) < 0 ) { console.error("Parameter radius is less than zero"); return; } var distance = p1.distance( p2 ); var half_dis = parseFloat(distance)/2.0; if( parseFloat(r) < half_dis ) { console.error("Parameter radius is too samll, please increass radius."); return; } if( parseFloat(half_dis) < 0.0001 ) { console.error("Distance between two point is too samll, please increase their distance."); return; } var v = p1.vector( p2 ); if (typeof(v) == "undefined") { console.error("Vector p1p2 is undefined"); return; } var middle_point = p1.middle( p2 ); // Roating vector p1p2 90 degrees clockwise var new_v_x = v.y; var new_v_y = -v.x; // Unifing the new vector var origin = new Point( 0.0, 0.0); var new_v = new Point( new_v_x, new_v_y ); var l = origin.distance( new_v ) var uni_v_x = parseFloat(new_v_x) / parseFloat(l); var uni_v_y = parseFloat(new_v_y) / parseFloat(l); var move_length = Math.sqrt( parseFloat(r) * parseFloat(r) - parseFloat(half_dis) * parseFloat(half_dis) ) ; var move_vector = new Point( parseFloat(uni_v_x) * parseFloat(move_length), parseFloat(uni_v_y) * parseFloat(move_length) ); var r_1 = middle_point.moveto( move_vector ); // Roating vector p1p2 90 degrees anti-clockwise move_vector = new Point( - parseFloat(uni_v_x) * parseFloat(move_length), -parseFloat(uni_v_y) * parseFloat(move_length) ); var r_2 = middle_point.moveto( move_vector ); return( [r_1, r_2] ); } // Testing function function test() { var p = new Point(-3,0); var p1 = new Point(3,0); var result = calCircleCenter( p, p1, 5 ) console.log('result = ', result ); } test();
测试结果:
result = [ Point { x: 0, y: -4, distance: [Function], middle: [Function], vector: [Function], moveto: [Function] }, Point { x: 0, y: 4, distance: [Function], middle: [Function], vector: [Function], moveto: [Function] } ]