根据两个圆的顺逆方向决定绘制哪一条切线:
圆1顺 - 圆2顺,绘制外切线
圆1顺 - 圆2逆,绘制内切线
圆1逆 - 圆2顺,绘制内切线
圆1逆 - 圆2逆,绘制外切线
总结:旋转方向一致,绘制外公切线,反之绘制内公切线。
每两个圆都有两条内切线或者两条外切线,再根据第二个圆的顺逆方向决定绘制哪一条切线。
/**
* @brief 根据圆1与圆2的圆心坐标、半径、顺逆方向绘制内外公切线
*/
function calculateTangentPoints(c1, r1, direction1, c2, r2, direction2) {
// 确定较大和较小的圆
var largeCircle, smallCircle, largeRadius, smallRadius, largeDirection, smallDirection;
if (r1 >= r2) {
largeCircle = c1;
smallCircle = c2;
largeRadius = r1;
smallRadius = r2;
largeDirection = direction1;
smallDirection = direction2;
} else {
largeCircle = c2;
smallCircle = c1;
largeRadius = r2;
smallRadius = r1;
largeDirection = direction2;
smallDirection = direction1;
}
// 计算两圆心之间的方位角和距离
var doubleCircle_azimuth = largeCircle.azimuthTo(smallCircle);
var centerDist = largeCircle.distanceTo(smallCircle);
// 确保圆心距离大于半径之差
if (centerDist <= Math.abs(largeRadius - smallRadius)) {
console.log("Error: 圆心距离小于半径.");
// 清空外切线
crosspointLineItem_ccw.path = [];
crosspointLineItem_cw.path = [];
// 清空内切线
innerTangentLineItem1.path = [];
innerTangentLineItem2.path = [];
return;
}
// 判断圆1和圆2的顺逆方向是否一致
var directionMatch = (largeDirection === smallDirection);
console.log("directionMatch", directionMatch)
// --------------------- 外切线 ---------------------
if (directionMatch) {
console.log("[绘制外切线]", direction1, direction2)
var angleRadians = Math.acos(Math.abs(largeRadius - smallRadius) / centerDist);
var angleDegrees = angleRadians * (180 / Math.PI);
// 第二个圆为顺时针
if(direction2) {
var _LeftCrosspoint_cw = largeCircle.atDistanceAndAzimuth(largeRadius, angleDegrees + doubleCircle_azimuth);
var _RightCrosspoint_cw = smallCircle.atDistanceAndAzimuth(smallRadius, angleDegrees + doubleCircle_azimuth);
// 绘制外公切线
crosspointLineItem_cw.path = [_LeftCrosspoint_cw, _RightCrosspoint_cw]
}
// 第二个圆为逆时针
else {
var _leftCrosspoint = largeCircle.atDistanceAndAzimuth(largeRadius, 90 - angleDegrees + (doubleCircle_azimuth - 90) )
var _RightCrosspoint = smallCircle.atDistanceAndAzimuth(smallRadius, (180 - angleDegrees - 90) + (doubleCircle_azimuth - 90) )
// 绘制外公切线
crosspointLineItem_ccw.path = [_leftCrosspoint, _RightCrosspoint]
}
// 清空内切线
innerTangentLineItem1.path = [];
innerTangentLineItem2.path = [];
}
// --------------------- 内切线 ---------------------
else {
console.log("[绘制内切线]", direction1, direction2)
var innerAngleRadians = Math.acos((largeRadius + smallRadius) / centerDist);
var innerAngleDegrees = innerAngleRadians * (180 / Math.PI);
// 内公切线角度
var innerAngle1 = doubleCircle_azimuth + innerAngleDegrees;
var innerAngle2 = doubleCircle_azimuth - innerAngleDegrees;
// 第二个圆为顺时针
if(direction2) {
var innerTangentPoint1Large = largeCircle.atDistanceAndAzimuth(largeRadius, innerAngle1);
var innerTangentPoint1Small = smallCircle.atDistanceAndAzimuth(smallRadius, innerAngle1 + 180);
// 绘制内公切线
innerTangentLineItem1.path = [innerTangentPoint1Large, innerTangentPoint1Small];
}
// 第二个圆为逆时针
else {
var innerTangentPoint2Large = largeCircle.atDistanceAndAzimuth(largeRadius, innerAngle2);
var innerTangentPoint2Small = smallCircle.atDistanceAndAzimuth(smallRadius, innerAngle2 + 180);
// 绘制内公切线
innerTangentLineItem2.path = [innerTangentPoint2Large, innerTangentPoint2Small];
}
// 清空外切线
crosspointLineItem_ccw.path = [];
crosspointLineItem_cw.path = [];
}
}