1. 当圆和直线相交时,直线起点和终点为p1,p2,o为圆心,r为半径,根据以下方式获得切点p3,把p1-p3画一条直线,计算新的直线p3-p2。以此循环即可绕圆
//p2与圆的切点p3()
getTangentPoint(p1:cc.Vec2,p2:cc.Vec2,O:cc.Vec2,r:number){
var px = p2.x
var py = p2.y
var cx = O.x
var cy = O.y
var p3 = new cc.Vec2()
//求点到圆心的距离
var distance = Math.sqrt((px-cx)*(px-cx)+(py-cy)*(py-cy))
//点到切点的距离
var length = Math.sqrt(distance*distance-r*r)
if (distance <= r){
cc.log("点在圆内,无切点")
return null
}
//点到圆心的单位向量
var ux = (cx-px)/distance
var uy = (cy-py)/distance
//计算切线与圆心连线的夹角
var angle = Math.asin(r/distance)
//向正反两个方向旋转单位向量
var q1x = ux * Math.cos(angle) - uy * Math.sin(angle)
var q1y = ux * Math.sin(angle) + uy * Math.cos(angle)
var q2x = ux * Math.cos(-angle) - uy * Math.sin(-angle)
var q2y = ux * Math.sin(-angle) + uy * Math.cos(-angle)
//得到新座标y
q1x = q1x * length + px
q1y = q1y * length + py
q2x = q2x * length + px
q2y = q2y * length + py
//哪个离p1近返回哪个?
var p1x = p1.x
var p1y = p1.y
var distance1 = Math.sqrt((p1x-q1x)*(p1x-q1x)+(p1y-q1y)*(p1y-q1y))
var distance2 = Math.sqrt((p1x-q2x)*(p1x-q2x)+(p1y-q2y)*(p1y-q2y))
if(distance1 < distance2){
p3.x = q1x
p3.y = q1y
}else{
p3.x = q2x
p3.y = q2y
}
return p3
}
2. 解开直线绕圆的思路:
每当有切点的时候,记下当前起点p1',圆心o。
判断直线的两个点p1p2,以及圆心组成的∠p2p1o,判断角度是否>90,当>90度时,可以回退,即清除p1p2直线,重新赋值p1 = p1',并且画线。
//两直线夹角
jiajiao(p, p1, p2) {
var x1 = p1.x;
var y1 = p1.y;
var x2 = p2.x;
var y2 = p2.y;
var x3 = p.x;
var y3 = p.y;
const getAngle = ({ x: x1, y: y1 }, { x: x2, y: y2 }) => {
const dot = x1 * x2 + y1 * y2
const det = x1 * y2 - y1 * x2
const angle = Math.atan2(det, dot) / Math.PI * 180
return Math.abs(angle)
}
const angle = getAngle({
x: x1 - x3,
y: y1 - y3,
}, {
x: x2 - x3,
y: y2 - y3,
});
return angle
}
if (window.circleDotArr && window.circleDotArr.length > 0) {
//p1起始点,圆心o,p2移动的点,当角度>90度就是撤回折点
var angle = this.jiajiao(p1, cc.v2(window.circleDotArr[window.circleDotArr.length - 1].x, window.circleDotArr[window.circleDotArr.length - 1].y), p2)
var flag = angle > 90
while (flag) {
p1 = window.p1Arr[window.p1Arr.length - 1]
this.prePoint = p1
window.p1Arr.pop()
window.circleDotArr.pop()
window.graphicsNodeArr[window.graphicsNodeArr.length - 1].destroy()
window.graphicsNodeArr.pop()
if (window.circleDotArr.length > 0) {
var angle = this.jiajiao(p1, cc.v2(window.circleDotArr[window.circleDotArr.length - 1].x, window.circleDotArr[window.circleDotArr.length - 1].y), p2)
var flag = angle > 90
} else {
flag = null
}
}
}