2013-03-08 107 views
1

我正在做一個關於robocup的學校項目,其中機器人正在與AI玩足球。由於一切工作正常,我仍然堅持一些東西。衝擊點:圓形碰撞

機器人是從頂視圖中繪製的簡單球體。不應允許雙方進入對方,並且應該在衝擊點上獲得新的更新位置。

由於碰撞處理程序只是檢查他們是否碰撞..我希望是否有辦法檢測到圓圈碰撞的地方。因此,我可以將碰撞球體的位置更新爲最後已知的非碰撞位置,以便它們不能相互穿過並反彈。

+0

由於它們只是圓圈,只需計算圓圈中心點之間的中點即可。如果圓圈有不同的半徑,則選擇一個圓圈並計算沿距離其中心一個半徑的線條的點。 – 2013-03-08 23:15:06

+1

@Chris:比Chris更簡單;見下文。 – 2013-03-08 23:15:52

+1

@PieterGeerkens我建議一種簡單的方法來計算實際的碰撞位置,從而計算出最接近的非碰撞位置,同時(可能)保持彼此的相對方向/角度,而不僅僅是他們是否碰撞。我認爲這就是傑西所要求的。 – 2013-03-08 23:21:05

回答

0

你需要做的是找到兩個圓之間的交點,可以是兩點,一點或沒有。這基本上是通過一起求解兩個圓的方程來完成的。這裏的數學:

http://www.analyzemath.com/CircleEq/circle_intersection.html

,因爲這是學校的,我會離開的編碼,到你:)

+0

感謝您的幫助。編碼不是問題。無法想出這樣做的公式。認爲我現在可以開始編碼了,謝謝! – 2013-03-08 23:45:29

2

圓的圓周上的所有點與圓心的距離相同。對於比賽場地上的每個圈子都是如此。

因此:當兩個圓心之間的距離爲< =它們相對半徑的總和時,兩個圓相互碰撞。

+0

聽起來Jesse已經在他們碰撞時正在接電話,但是詢問_where_發生了碰撞。 – 2013-03-08 23:16:45

+0

克里斯在說什麼。碰撞檢測不是問題。它會發現圓環在2D環境中的相交位置,以獲取X&Y位置,以將它們放回到尚未與其碰撞的位置。所以他們在圈子的每一邊停止移動。 – 2013-03-08 23:44:39

0

好,我們已經標出一個答案,但我去了,把一個全功能的一塊的代碼,所以也許你可以使用它。 :)從我的評論:

因爲他們只是圓圈,只需計算 圈子的中心點之間的中點。如果圓圈有不同的半徑,則選擇一個圓圈 ,並計算其中心距離 一個半徑的線上的點。

這可能是一個簡單的實現。我爲它創建了一些非常微薄的輔助類;我完全鼓勵擴展它們,使結構真正一成不變,以及所有那些優秀的爵士樂,但現在可以用於演示目的。

因此,對於輔助類:

public struct Point 
{ 
    public double X; 
    public double Y; 

    public double Distance(Point otherPoint) 
    { 
     double deltaX = this.X - otherPoint.X; 
     double deltaY = this.Y - otherPoint.Y; 
     return System.Math.Sqrt(deltaX * deltaX + deltaY * deltaY); 
    } 

    public override string ToString() 
    { 
     return String.Format("({0}, {1})", X, Y); 
    } 
} 

public struct Polar 
{ 
    public double Radius; 
    public double Angle; 

    public double X { get { return Radius * System.Math.Cos(Angle); } } 
    public double Y { get { return Radius * System.Math.Sin(Angle); } } 

    public Point ToCartesian() 
    { 
     return new Point() { X = X, Y = Y }; 
    } 
} 

public class Circle 
{ 
    public double Radius { get; set; } 
    public Point Position { get; set; } 
} 

我們的肉和土豆類/方法是這樣的:

public class CollisionResult 
{ 
    public Circle Circle1 { get; private set; } 
    public Circle Circle2 { get; private set; } 

    public Point Circle1SafeLocation { get; private set; } 
    public Point Circle2SafeLocation { get; private set; } 

    public Point CollisionLocation { get; private set; } 

    public CollisionResult(Circle circle1, Circle circle2) 
    { 
     this.Circle1 = circle1; 
     this.Circle2 = circle2; 
    } 

    public bool CalculateCollision() 
    { 
     double distanceFromCentres = Circle1.Position.Distance(Circle2.Position); 
     if (distanceFromCentres >= Circle1.Radius + Circle2.Radius) 
      return false; 

     double angleBetweenCircles = System.Math.Atan2(Circle2.Position.Y - Circle1.Position.Y, Circle2.Position.X - Circle1.Position.X); 

     Point midpointBetweenCircles = new Point(){X = (Circle1.Position.X + Circle2.Position.X)/2, Y = (Circle1.Position.Y + Circle2.Position.Y)/2}; 

     Point circle1Offset = (new Polar() { Radius = Circle1.Radius, Angle = System.Math.PI + angleBetweenCircles }).ToCartesian(); 
     Point circle2Offset = (new Polar() { Radius = Circle2.Radius, Angle = angleBetweenCircles }).ToCartesian(); 

     CollisionLocation = midpointBetweenCircles; 
     Circle1SafeLocation = new Point(){X = midpointBetweenCircles.X + circle1Offset.X, Y = midpointBetweenCircles.Y + circle1Offset.Y }; 
     Circle2SafeLocation = new Point(){X = midpointBetweenCircles.X + circle2Offset.X, Y = midpointBetweenCircles.Y + circle2Offset.Y }; 

     return true; 
    } 
} 

使用可能看起來像:

private void CheckCollision(Circle circle1, Circle circle2) 
{ 
    CollisionResult result = new CollisionResult(circle1, circle2); 
    if (result.CalculateCollision()) 
    { 
     Console.WriteLine(String.Format("Collision detected at {0}! Safe location for circle 1: {1}, circle 2: {2}", result.CollisionLocation, result.Circle1SafeLocation, result.Circle2SafeLocation)); 
    } 
    else 
    { 
     Console.WriteLine("Did not collide."); 
    } 
} 

var circle1 = new Circle() {Radius = 5, Position = new Point(){X = 0, Y = 0} }; 
var circle2 = new Circle() {Radius = 5, Position = new Point(){X = 10, Y = 0} }; 
var circle3 = new Circle() {Radius = 3, Position = new Point(){X = 0, Y = 1} }; 
var circle4 = new Circle() {Radius = 5, Position = new Point(){X = 3, Y = 7} }; 

CheckCollision(circle1, circle2); 
CheckCollision(circle3, circle4); 

輸出:

Did not collide. 
Collision detected at (1.5, 4)! Safe location for circle 1: (0.158359213500125, 1.31671842700025), circle 2: (3.73606797749979, 8.47213595499958) 

我不知道在你的情況下是否有必要處理計算兩個圓的真實交點的複雜性(它們將在兩點相交)等等。有可能沿着這些線路就足夠了。我絕對鼓勵健康的單元測試,並讓我的課程超出我在這裏的範圍適當的。:)

編輯:值得注意的是在這種情況下,這將取決於你想用它來做爲你的應用是什麼,是當圓重疊,它只是計算它們之間的中點然後移動每圈從該中點離開各自的半徑。因此,根據圈子的速度和大小,或者他們如何移動,可能會產生奇怪的結果。例如,如果你有一個半徑爲10的大圓圈坐着,那麼你就會在距離大圓圈中心只有0.5的距離處放置一個半徑爲1的圓圈,那麼這個大圓圈將會移動大約9.75個單位!如果你沒有進入重疊的條件,那麼這可能不是什麼大問題。我認爲至少這會給你一些信息關於碰撞,然後如何你想你的圈子作出反應,結果將取決於你。