您的位置:首页 > 其它

多边形裁剪圆的实现细节之求直线段与圆的交点

2015-05-25 20:23 274 查看
1.求直线段与圆的交点

(1)由线段端点P1(x1,y1)P2(x2,y2)得到线段所在直线的方程

ax+by+c=0

(2)由圆心P0(x0,y0)和半径r得到圆的方程

(x-x0)2+(y-y0)2=r2

(3)由点到圆的距离公式算出圆心到线段的距离d

(4)我先假设圆与线段有两个公共点,将线段P1P2写成参数方程形式,t为参数。

x=x1+(x2-x1)*t

y=y1+(y2-y1)*t

0<=t<=1

这里我分别持有两个公共点类的对象,含有属性x,y和t。x与y是公共点坐标信息,参数t用来表示该点即使为直线与圆公共点是否不在线段范围内。

(5)若d>r则没有公共点,我们将两个公共点对象的参数t置为不合法,这样讲不被记录为多边形与圆的公共点。

(6)若d<=r则通过圆方程与线段参数方程求解公共点坐标与参数,将参数t合法的公共点对象记录为多边形与圆的公共点。这里对于d=r的情况视为有两个相同的公共点输出。

实现表现为项目中的SegCrossoverCircle函数

void SegCrossoverCircle(MyLine line, MyCircle circle, CrossoverPoint &cp1, CrossoverPoint &cp2)
{
//初始化图像信息
double x1, y1, x2, y2, x0, y0, r;
x1 = line.startpoint.x;
y1 = line.startpoint.y;
x2 = line.endpoint.x;
y2 = line.endpoint.y;
x0 = circle.center.x;
y0 = circle.center.y;
r = circle.radius;

//寻找交点解参数方程
double a, b, c, a1, b1, c1, d, delta, t1, t2;
a = y0 - y1;
b = x1 - x0;
c = x0*y1 - x1*y0;
d = abs(a*x0 + b*y0 + c) / sqrt(a*a + b*b + esp);
a1 = x1*x1 + x2*x2 + y1*y1 + y2*y2 - 2 * x1*x2 - 2 * y1*y2;
b1 = 2 * (x0*x1 + x1*x2 + y0*y1 + y1*y2 - x0*x2 - y0*y2 - x1*x1 - y1*y1);
c1 = x0*x0 + x1*x1 + y0*y0 + y1*y1 - 2 * x0*x1 - 2 * y0*y1 - r*r;
delta = b1*b1 - 4 * a1*c1;

//出交点
if (d <= r)
{
if (delta < esp)
{
//相切只出一个
double cos1, sin1;
cp1.t = 2;
t1 = (-b1 + sqrt(delta)) / (2 * a1);
cp1.t = t1;
cp1.x = x1 + t1*(x2 - x1);
cp1.y = y1 + t1*(y2 - y1);
cos1 = (cp1.x - x0) / r;
sin1 = (cp1.y - y0) / r;
if (abs(sin(acos(cos1)) - sin1) < esp)
{
cp1.a = acos(cos1);
}
else
{
cp1.a = 2 * PI - acos(cos1);
}

//让pt2报废不算
cp2.t = 2;

}
else
{
double cos1, sin1, cos2, sin2;
t1 = (-b1 + sqrt(delta)) / (2 * a1);
t2 = (-b1 - sqrt(delta)) / (2 * a1);
cp1.t = t1;
cp1.x = x1 + t1*(x2 - x1);
cp1.y = y1 + t1*(y2 - y1);
cos1 = (cp1.x - x0) / r;
sin1 = (cp1.y - y0) / r;
if (abs(sin(acos(cos1)) - sin1) < esp)
{
cp1.a = acos(cos1);
}
else
{
cp1.a = 2 * PI - acos(cos1);
}

cp2.t = t2;
cp2.x = x1 + t2*(x2 - x1);
cp2.y = y1 + t2*(y2 - y1);
cos2 = (cp2.x - x0) / r;
sin2 = (cp2.y - y0) / r;
if (abs(sin(acos(cos2)) - sin2) < esp)
{
cp2.a = acos(cos2);
}
else
{
cp2.a = 2 * PI - acos(cos2);
}

}
}
else
{
//没交点让pt1,pt2都报废
cp1.t = 2;
cp2.t = 2;
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: