2010-11-05 73 views
28

我在圓周上有三個點:從三個點查找圓心的算法是什麼?

pt A =(A.x,A.y); pt B =(B.x,B.y); pt C =(C.x,C.y);

如何計算圓心?

在Processing(Java)中實現它。

我找到了答案和實施工作方案:

pt circleCenter(pt A, pt B, pt C) { 

    float yDelta_a = B.y - A.y; 
    float xDelta_a = B.x - A.x; 
    float yDelta_b = C.y - B.y; 
    float xDelta_b = C.x - B.x; 
    pt center = P(0,0); 

    float aSlope = yDelta_a/xDelta_a; 
    float bSlope = yDelta_b/xDelta_b; 
    center.x = (aSlope*bSlope*(A.y - C.y) + bSlope*(A.x + B.x) 
     - aSlope*(B.x+C.x))/(2* (bSlope-aSlope)); 
    center.y = -1*(center.x - (A.x+B.x)/2)/aSlope + (A.y+B.y)/2; 

    return center; 
    } 
+0

http://mathforum.org/library/drmath/view/55233.html – 2010-11-05 03:40:59

+2

感謝一噸張貼在回答你的問題。 – 2011-04-14 20:46:21

+1

如果'B.x - A.x'或'C.x - B.x'爲零,則您的解決方案會產生奇怪的結果,因爲您除以零。 – gexicide 2015-06-14 20:00:12

回答

14

它可以是一個相當的深度計算。這裏有一個簡單的步驟:http://paulbourke.net/geometry/circlesphere/。一旦你有圓的方程,你可以簡單地把它放在一個涉及H和K的形式中。點(h,k)將成爲中心。

(向下滾動在鏈路小的方式來獲得的方程)

+0

這是使我找到答案的頁面。我自己實現爲: – 2010-11-05 04:09:53

+1

pt circleCenter(pt A,pt B,pt C){float:yDelta_a = B.y - A.y; \t float xDelta_a = B.x - A.x; \t float yDelta_b = C.y - B.y; \t float xDelta_b = C.x - B.x; pt center = P(0,0); \t float aSlope = yDelta_a/xDelta_a; \t float bSlope = yDelta_b/xDelta_b; \t center.x =(aSlope * bSlope *(A.y-C.y)+ bSlope *(A.x + B。x) \t \t-aSlope *(B.x + C.x))/(2 *(bSlope-aSlope)); (A.x + B.x)/ 2)/ aSlope +(A.y + B.y)/ 2; return center; } – 2010-11-05 04:10:15

15

這裏是我的Java接口,躲着錯誤情況時,決定用一個非常優雅的IllegalArgumentException消失了,我的做法與「點應對是兩個相距甚遠「或」點在一條線上「的條件。此外,這還計算了你的相交斜率方法不會做的半徑(並處理特殊情況)。

public class CircleThree 
{ 
    static final double TOL = 0.0000001; 

    public static Circle circleFromPoints(final Point p1, final Point p2, final Point p3) 
    { 
    final double offset = Math.pow(p2.x,2) + Math.pow(p2.y,2); 
    final double bc = (Math.pow(p1.x,2) + Math.pow(p1.y,2) - offset)/2.0; 
    final double cd = (offset - Math.pow(p3.x, 2) - Math.pow(p3.y, 2))/2.0; 
    final double det = (p1.x - p2.x) * (p2.y - p3.y) - (p2.x - p3.x)* (p1.y - p2.y); 

    if (Math.abs(det) < TOL) { throw new IllegalArgumentException("Yeah, lazy."); } 

    final double idet = 1/det; 

    final double centerx = (bc * (p2.y - p3.y) - cd * (p1.y - p2.y)) * idet; 
    final double centery = (cd * (p1.x - p2.x) - bc * (p2.x - p3.x)) * idet; 
    final double radius = 
     Math.sqrt(Math.pow(p2.x - centerx,2) + Math.pow(p2.y-centery,2)); 

    return new Circle(new Point(centerx,centery),radius); 
    } 

    static class Circle 
    { 
    final Point center; 
    final double radius; 
    public Circle(Point center, double radius) 
    { 
     this.center = center; this.radius = radius; 
    } 
    @Override 
    public String toString() 
    { 
     return new StringBuilder().append("Center= ").append(center).append(", r=").append(radius).toString(); 
    } 
    } 

    static class Point 
    { 
    final double x,y; 

    public Point(double x, double y) 
    { 
     this.x = x; this.y = y; 
    } 
    @Override 
    public String toString() 
    { 
     return "("+x+","+y+")"; 
    } 

    } 

    public static void main(String[] args) 
    { 
    Point p1 = new Point(0.0,1.0); 
    Point p2 = new Point(1.0,0.0); 
    Point p3 = new Point(2.0,1.0); 
    Circle c = circleFromPoints(p1, p2, p3); 
    System.out.println(c); 
    } 

} 

algorithm from here

void circle_vvv(circle *c) 
{ 
    c->center.w = 1.0; 
    vertex *v1 = (vertex *)c->c.p1; 
    vertex *v2 = (vertex *)c->c.p2; 
    vertex *v3 = (vertex *)c->c.p3; 
    float bx = v1->xw; float by = v1->yw; 
    float cx = v2->xw; float cy = v2->yw; 
    float dx = v3->xw; float dy = v3->yw; 
    float temp = cx*cx+cy*cy; 
    float bc = (bx*bx + by*by - temp)/2.0; 
    float cd = (temp - dx*dx - dy*dy)/2.0; 
    float det = (bx-cx)*(cy-dy)-(cx-dx)*(by-cy); 
    if (fabs(det) < 1.0e-6) { 
     c->center.xw = c->center.yw = 1.0; 
     c->center.w = 0.0; 
     c->v1 = *v1; 
     c->v2 = *v2; 
     c->v3 = *v3; 
     return; 
     } 
    det = 1/det; 
    c->center.xw = (bc*(cy-dy)-cd*(by-cy))*det; 
    c->center.yw = ((bx-cx)*cd-(cx-dx)*bc)*det; 
    cx = c->center.xw; cy = c->center.yw; 
    c->radius = sqrt((cx-bx)*(cx-bx)+(cy-by)*(cy-by)); 
} 
+0

我無法看到哪3個是原始頂點。 v1,v2和v3? – 2010-11-05 03:48:11

+0

是的,這不是很好的代碼;我把它拆了。 v1,2,3是原始頂點。 (bx,by),(cx,cy),(dx,dy)是coords。 – andersoj 2010-11-05 03:53:22

+0

@Russell Strauss:我提供了這個代碼的Java端口,這使得流程更加清晰。 – andersoj 2010-11-05 12:56:51

4

我一直在尋找類似的算法,當我徘徊在這個問題上。 接收了您的代碼,但發現在斜率爲0或無窮大的情況下(xDelta_a或xDelta_b爲0時可能爲true),這不起作用。

我糾正了算法,這裏是我的代碼。 注意:我使用了Objective-C編程語言,並且只是更改了點值初始化的代碼,所以如果這是錯誤的,我確信使用java工作的程序員可以更正它。然而,邏輯對於所有人來說都是一樣的(上帝保佑算法!! :))

就我自己的功能測試而言,完美地工作正常。 請讓我知道在任何時候邏輯是錯誤的。

pt circleCenter(pt A, pt B, pt C) { 

float yDelta_a = B.y - A.y; 
float xDelta_a = B.x - A.x; 
float yDelta_b = C.y - B.y; 
float xDelta_b = C.x - B.x; 
pt center = P(0,0); 

float aSlope = yDelta_a/xDelta_a; 
float bSlope = yDelta_b/xDelta_b; 

pt AB_Mid = P((A.x+B.x)/2, (A.y+B.y)/2); 
pt BC_Mid = P((B.x+C.x)/2, (B.y+C.y)/2); 

if(yDelta_a == 0)   //aSlope == 0 
{ 
    center.x = AB_Mid.x; 
    if (xDelta_b == 0)   //bSlope == INFINITY 
    { 
     center.y = BC_Mid.y; 
    } 
    else 
    { 
     center.y = BC_Mid.y + (BC_Mid.x-center.x)/bSlope; 
    } 
} 
else if (yDelta_b == 0)    //bSlope == 0 
{ 
    center.x = BC_Mid.x; 
    if (xDelta_a == 0)    //aSlope == INFINITY 
    { 
     center.y = AB_Mid.y; 
    } 
    else 
    { 
     center.y = AB_Mid.y + (AB_Mid.x-center.x)/aSlope; 
    } 
} 
else if (xDelta_a == 0)  //aSlope == INFINITY 
{ 
    center.y = AB_Mid.y; 
    center.x = bSlope*(BC_Mid.y-center.y) + BC_Mid.x; 
} 
else if (xDelta_b == 0)  //bSlope == INFINITY 
{ 
    center.y = BC_Mid.y; 
    center.x = aSlope*(AB_Mid.y-center.y) + AB_Mid.x; 
} 
else 
{ 
    center.x = (aSlope*bSlope*(AB_Mid.y-BC_Mid.y) - aSlope*BC_Mid.x + bSlope*AB_Mid.x)/(bSlope-aSlope); 
    center.y = AB_Mid.y - (center.x - AB_Mid.x)/aSlope; 
} 

return center; 
} 
2
public Vector2 CarculateCircleCenter(Vector2 p1, Vector2 p2, Vector2 p3) 
{ 
    Vector2 center = new Vector2(); 
    float ma = (p2.y - p1.y)/(p2.x - p1.x); 
    float mb = (p3.y - p2.y)/(p3.x - p2.x); 
    center.x = (ma * mb * (p1.y - p3.y) + mb * (p1.x - p2.x) - ma * (p2.x + p3.x))/(2 * (mb - ma)); 
    center.y = (-1/ma) * (center.x - (p1.x + p2.x) * 0.5) + (p1.y + p2.y) * 0.5; 
    return center; 
} 
+1

錯字:'mb *(p1.x - p2.x)'應該是'mb *(p1.x + p2.x)' – 2016-01-14 23:42:33