求直线与圆的交点的问题

时间:2022-08-30 10:37:06
我用圆的方程式和直线方程式连理起来求交点。。但是求出来的交点老是不对。。。圆心和半径都是已知的。。直线方程也是已知的。。谁知道有更好一点的方法啊。。。

16 个解决方案

#1


这是程序设计问题吗

#2


是啊。。。vc问题啊。。。

#3


有谁知道算法的可以告诉一下啊。。。。。。。最主要是速度要快。。。有代码最好了。。。。

#4


哦,说说看你是怎么做的吧

#5


我感觉你说的不对,应该是点不能完全吻合吧,因为误差的原因。

现在的圆仿佛大多使用Bresenham算法,你模拟再花一遍圆(遍历圆上面的点),看经过的点是否满足你的直线方程,或许可以。当然要做一写优化。

#6


用圆上所有点,代入直线方程,方程成立则是交点,

#7


其实我主要是要求一段圆弧和线的交点。。。圆弧所在圆的圆心和半径我都求出来了。。直线方程我也求出来了。。。并且这条线可以肯定是和该圆弧有交点的。。只是想要一个快速求交点的算法和判断是哪一个交点和该圆弧相交(因为可以求出两个交点,一个和该圆弧相交,另一个和圆相交的点不需要)。。。

#8


没有什么好办法,直接解方程组

#9


世界坐标转本地坐标求交,然后再转回去.

#10


楼主不用费事了,直接去我的blog,其中有个文章“直线圆裁剪程序”,那个有现成的

本人blog地址:http://blog.csdn.net/vbspine

#11


ls 方法不错,up!

#12


求直线上的每一个点到圆心的距离是否等于圆的半径。等于的就是要找的那个点。

#13


现在我已经把两个交点求出来了,现在问题是怎么取得我想要的那个点,就是怎么判断这个圆上的一段指定圆弧和线的交点,而另一个交点没用,要过滤掉,,现在我老是求反了,把和圆弧的交点过滤了,把另一个没用的交点画出来了,每次都是反的啊。。。。不知道各位能否告诉我一个判断的方法啊。。谢谢各位回帖

#14


兄弟,用这个圆弧的横纵坐标,和交点进行做差乘法运算,然后看正负

#15


主要问题是你的精度的问题,因为你在运算过程中涉及到了double
而传进去的点都是int型的。
建议把结果强制转成int,试下。。。

我简单的写了个

我的圆心(200,300)半径 50
直线起点 (100,260) 终点(400,450)

//下面这个函数得到交点,如果有2个就返回第一个求出的。
CPoint GetPoint(int cx,int cy,int r,int stx,int sty,int edx,int edy )
{
    //(x - cx )^2 + (y - cy)^2 = r^2
    //y = kx +b

    //求得直线方程
    double k = ((double)(edy - sty) ) / (edx - stx);
    double b = edy - k*edx;
  
  //列方程
  /*
    (1 + k^2)*x^2 - x*(2*cx -2*k*(b -cy) ) + cx*cx + ( b - cy)*(b - cy) - r*r = 0
  */
  double x1,y1,x2,y2;
  double c = cx*cx + (b - cy)*(b- cy) -r*r;
  double a = (1 + k*k);
  double b1 = (2*cx - 2*k*(b - cy));
  //得到下面的简化方程
  // a*x^2 - b1*x + c = 0;
  
  double tmp = sqrt(b1*b1 - 4*a*c);
  x1 = ( b1 + tmp )/(2*a);
  y1 = k*x1 + b;
  x2 = ( b2 - tmp)/(2*a);
  y2 = k*x2 + b;

 //判断求出的点是否在圆上

 double res = (x1 -cx)*(x1 -cx) + (y1 - cy)*(y1 -cy);
 CPoint p; 
 if( (int)res == r*r)  //我这里 r = 50,res = 2500.632,还是比较准确的
  {
    MessageBox("get it");
    p.x = x1;
    p.y = y1;  
 }
 else
   {
    p.x = x2;
    p.y = y2;
   }
return p;
}

在OnPaint里面验证下
CPaint dc(this);
Cpoint tmp = GetPoint(200,300,50,100,260,400,450);
//为了好看出来,画了个tmp为圆心,半径为3的圆
dc.Elipse(tmp.x + 3,tmp.y + 3, tmp.x - 3, tmp.y -3);



我自己测试过是对的

#16


up

#1


这是程序设计问题吗

#2


是啊。。。vc问题啊。。。

#3


有谁知道算法的可以告诉一下啊。。。。。。。最主要是速度要快。。。有代码最好了。。。。

#4


哦,说说看你是怎么做的吧

#5


我感觉你说的不对,应该是点不能完全吻合吧,因为误差的原因。

现在的圆仿佛大多使用Bresenham算法,你模拟再花一遍圆(遍历圆上面的点),看经过的点是否满足你的直线方程,或许可以。当然要做一写优化。

#6


用圆上所有点,代入直线方程,方程成立则是交点,

#7


其实我主要是要求一段圆弧和线的交点。。。圆弧所在圆的圆心和半径我都求出来了。。直线方程我也求出来了。。。并且这条线可以肯定是和该圆弧有交点的。。只是想要一个快速求交点的算法和判断是哪一个交点和该圆弧相交(因为可以求出两个交点,一个和该圆弧相交,另一个和圆相交的点不需要)。。。

#8


没有什么好办法,直接解方程组

#9


世界坐标转本地坐标求交,然后再转回去.

#10


楼主不用费事了,直接去我的blog,其中有个文章“直线圆裁剪程序”,那个有现成的

本人blog地址:http://blog.csdn.net/vbspine

#11


ls 方法不错,up!

#12


求直线上的每一个点到圆心的距离是否等于圆的半径。等于的就是要找的那个点。

#13


现在我已经把两个交点求出来了,现在问题是怎么取得我想要的那个点,就是怎么判断这个圆上的一段指定圆弧和线的交点,而另一个交点没用,要过滤掉,,现在我老是求反了,把和圆弧的交点过滤了,把另一个没用的交点画出来了,每次都是反的啊。。。。不知道各位能否告诉我一个判断的方法啊。。谢谢各位回帖

#14


兄弟,用这个圆弧的横纵坐标,和交点进行做差乘法运算,然后看正负

#15


主要问题是你的精度的问题,因为你在运算过程中涉及到了double
而传进去的点都是int型的。
建议把结果强制转成int,试下。。。

我简单的写了个

我的圆心(200,300)半径 50
直线起点 (100,260) 终点(400,450)

//下面这个函数得到交点,如果有2个就返回第一个求出的。
CPoint GetPoint(int cx,int cy,int r,int stx,int sty,int edx,int edy )
{
    //(x - cx )^2 + (y - cy)^2 = r^2
    //y = kx +b

    //求得直线方程
    double k = ((double)(edy - sty) ) / (edx - stx);
    double b = edy - k*edx;
  
  //列方程
  /*
    (1 + k^2)*x^2 - x*(2*cx -2*k*(b -cy) ) + cx*cx + ( b - cy)*(b - cy) - r*r = 0
  */
  double x1,y1,x2,y2;
  double c = cx*cx + (b - cy)*(b- cy) -r*r;
  double a = (1 + k*k);
  double b1 = (2*cx - 2*k*(b - cy));
  //得到下面的简化方程
  // a*x^2 - b1*x + c = 0;
  
  double tmp = sqrt(b1*b1 - 4*a*c);
  x1 = ( b1 + tmp )/(2*a);
  y1 = k*x1 + b;
  x2 = ( b2 - tmp)/(2*a);
  y2 = k*x2 + b;

 //判断求出的点是否在圆上

 double res = (x1 -cx)*(x1 -cx) + (y1 - cy)*(y1 -cy);
 CPoint p; 
 if( (int)res == r*r)  //我这里 r = 50,res = 2500.632,还是比较准确的
  {
    MessageBox("get it");
    p.x = x1;
    p.y = y1;  
 }
 else
   {
    p.x = x2;
    p.y = y2;
   }
return p;
}

在OnPaint里面验证下
CPaint dc(this);
Cpoint tmp = GetPoint(200,300,50,100,260,400,450);
//为了好看出来,画了个tmp为圆心,半径为3的圆
dc.Elipse(tmp.x + 3,tmp.y + 3, tmp.x - 3, tmp.y -3);



我自己测试过是对的

#16


up