繁体   English   中英

给出三个点时找到圆心

[英]find center of circle when three points are given

我研究了这个链接并进行了相应的编码,但是对于链接中解释的例子得到了错误的答案。在求解方程期间,我从等式1中减去等式2,从等式2中减去等式3然后继续进行。 请检查链接以获得澄清。

我的代码是:

include<stdio.h>
int is_formCircle(float a1,float b1,float a2,float b2,float a3,float b3) {
  float p1=a2-a1;
  float p2=a3-a2;
  float p3=b2-b1;
  float p4=b3-b2;
  float alpha=(a1+a2)*(a1-a2) + (b1+b2)*(b1-b2);
  float beta =(a2+a3)*(a2-a3) + (b2+b3)*(b2-b3);
  float y1=p1*beta - p2*alpha;
  float y2=p2*p3 - p1*p4;
  if(y2==0 || y1==0) return 1;
  float y=y1/y2;
  float x1 = 2*p4*y + beta;
  float x2 = 2*p2;
  float x = x1/x2;
  printf("x=%f  y=%f\n",x,y);
  return 0;
}
int main() {
 float a1,a2,a3,a4,b1,b2,b3,b4;
 a1=4.0;
 b1=1.0;
 a2=-3.0;
 b2=7.0;
 a3=5.0;
 b3=-2.0;
 is_formCircle(a1,b1,a2,b2,a3,b3);
 return 0;
}

我的另一个代码:

#include<stdio.h>
int is_formCircle(float a1,float b1,float a2,float b2,float a3,float b3) {                  
  float mid1,mid2,mid3,mid4,m1,m2,D,Dx,Dy,x,y;
  mid1 = a1+(a2-a1)/2;
  mid2 = b1+(b2-b1)/2;
  mid3 = a2+(a3-a2)/2;
  mid4 = b2+(b3-b2)/2;
  m1=(b2-b1)/(a2-a1);
  m2=(b3-b2)/(a3-a2);
  m1=-1*m1;
  m2=-1*m2;
  D=m2-m1;
  Dx=mid2-(m1*mid1) + (mid3*m2) - mid4;
  Dy=(m1*(mid3*m2-mid4))-(m2*(mid1*m1-mid2));
  x=Dx/D;
  y=Dy/D;
  printf("%f %f",x,y);    
  return 0;
}
int main() {
 float a1,a2,a3,b1,b2,b3;      
 a1=4.0;
 b1=1.0;
 a2=-3.0;
 b2=7.0;
 a3=5.0;
 b3=-2.0;
 is_formCircle(a1,b1,a2,b2,a3,b3);      
 return 0;
}

为什么我的代码给出了错误的答案?

链接中给出的解决方案是一个“盲”解决方案,即,您知道方程式,繁荣解决它。

但是, 如果您更深入地了解场景背后的内容 ,您将能够:

  1. 编写更易读,可靠,灵活的代码。
  2. 轻松调试。

从等式2中减去等式1时会发生什么? 你实际上试图找到直线的方程,描述与点1和点2等距的那些点。然后,你对第2点和第3点做同样的事情。最后,你找到这些点与线之间的交点,给你圆圈的中心。

你如何描述与点1和2等距的点的直线? 取两点中间的点,然后沿与点1和点2之间的方向垂直的方向前进。

如果这不是绝对清楚的,拿一张纸画一个例子:放点1,2和3,找到两条线并找到交点。

既然你理解了一切,用两个函数重塑你的代码,在两个点之间找到等距的线,另一个计算两条线之间的交点...


在编辑之后,代码看起来更好,尽管理解起来并不简单。 我认为错误是当你解决两条线的交叉时,不要忘记你是在参数形式下:

Dx = (mid4-mid2) - m2*(mid3-mid1);

lambda=Dx/D;

x = mid1 + lambda*m1;
y = mid2 + lambda*1.0;

使用Matlab以图形方式检查。

我不得不说,如果您按照列出的链接,它将有助于保持变量名称相同。 我们可以更好地理解算法,看到x1,y1,x2,y2,x3,y3而不是p1,p2,p3,p4,alpha和beta。 实际上,我在您的算法中看不到与链接匹配的内容。 我并不想像评论一样严厉(如果你担心将float切换为double,这对于typedef来说是一个非常好的例子),但是当你不必转换时,调试算法是最简单的变量名。

我建议只使用它们为链接中的h和k提供的内容,即通过计算3x3矩阵的行列式来完成。 你可以找到很多参考资料

我将创建两个函数,如下所示:

float calculateH(float x1, float y1, float x2, float y2, float x3, float y3) {
    float numerator = (x2*x2+y2*y2)*y3 - (x3*x3+y3*y3)*y2 - 
                      ((x1*x1+y1*y1)*y3 - (x3*x3+y3*y3)*y1) +
                      (x1*x1+y1*y1)*y2 - (x2*x2+y2*y2)*y1;
    float denominator = (x2*y3-x3*y2) -
                        (x1*y3-x3*y1) +
                        (x1*y2-x2*y1);
    denominator *= 2;
    return numerator / denominator;
}
float calculateK(float x1, float y1, float x2, float y2, float x3, float y3) {
    float numerator = x2*(x3*x3+y3*y3) - x3*(x2*x2+y2*y2) -
                      (x1*(x3*x3+y3*y3) - x3*(x1*x1+y1*y1)) +
                      x1*(x2*x2+y2*y2) - x2*(x1*x1+y1*y1);
    float denominator = (x2*y3-x3*y2) -
                        (x1*y3-x3*y1) +
                        (x1*y2-x2*y1);
    denominator *= 2;
    return numerator / denominator;
}

然后你的is_formCircle就是:

float is_formCircle(float x1, float y1, float x2, float y2, float x3, float y3) {
    float h = calculateH(x1, y1, x2, y2, x3, y3);
    float k = calculateK(x1, y1, x2, y2, x3, y3);
    printf("x=%f  y=%f\n",h,k);
}

有很多方法可以对此进行优化,并且我有可能将任何决定因素计算错误,但它应该让你前进。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM