2014-10-08 3 views
2

Я пытаюсь создать кольцо кругов, аля:Как позиционировать кольцо кругов с максимальным радиусом кольца

Кружки имеют заданный радиус, circleRadius. Кольцо имеет максимальный радиус, maxRingRadius. Число кругов может быть любым целым числом, circles, которое необходимо рассчитать вместе с фактическим радиусом кольца, ringRadius. Круги, когда их центры размещены ringRadius единиц из центра кольца, должны быть точно трогательными, как на диаграмме.

Учитывая circleRadius и maxRingRadius, как можно найти ближайший (или следующий маленький) ringRadius который будет соответствовать целому числу circles, а затем расположить эти круги?

static Vector3[] RingOfCircles(float maxRingRadius, float circleRadius) { 
     //int circles = ...; // calculate this? 
     //float ringRadius = ...; // calculate this? 

     //Edit: Solution. These three lines are adapted from InBetween's GetNextSmallerRingRadius function but Unity3d-ized and without validation 
     int circles = Mathf.RoundToInt(Mathf.PI/Mathf.Asin(circleRadius/maxRingRadius)); 
     float centralAngle = 2 * Mathf.PI/(numberOfCircles - 1); 
     float ringRadius = circleRadius/Mathf.Sin(centralAngle/2); 

     // create ring of center points 
     float radsPerCircle = (Mathf.PI * 2)/circles; 
     Vector3[] centerPoints = new Vector3[circles]; 
     for (int i=0; i < circles; i++) { 
      float angle = i * radsPerCircle; 
      centerPoints[i] = new Vector3(
       Mathf.Sin(angle) * ringRadius, 
       Mathf.Cos(angle) * ringRadius, 
       0); 
     } 

     return centerPoints; 
    } 
` 

Примечание: maxRingRadius может точно также быть minRingRadius или approximateRingRadius для моих целей. Но ringRadius должен определить следующее ближайшее «кольцо», которое может содержать целые числа кругов.


Решено: A visual confirmation of the solution Визуальное подтверждение решения

ответ

1

Если я понял ваш вопрос правильно, это должно сделать это:

public static double GetNextSmallerRingRadius(double startingRingRadius, double circleRadius) 
{ 
    Debug.Assert(startingRingRadius >= 0); 
    Debug.Assert(circleRadius > 0); 

    int currentNumberOfCircles = GetCurrentNumberOfCircles(startingRingRadius, circleRadius); 

    //Let's get trivial cases out of the way 
    if (currentNumberOfCircles == 1) 
     throw new ArgumentException(); 
    if (currentNumberOfCircles == 2) 
     return 0; //trivial solution for 1 circle. 
    if (currentNumberOfCircles == 3) 
     return circleRadius; //trivial solution for 2 circles. 

    double centralAngle = 2 * Math.PI/(currentNumberOfCircles - 1); 
    return circleRadius/Math.Sin(centralAngle/2); 
} 

public static double GetNextLargerRingRadius(double startingRingRadius, double circleRadius) 
{ 
    Debug.Assert(startingRingRadius >= 0); 
    Debug.Assert(circleRadius > 0); 

    int currentNumberOfCircles = GetCurrentNumberOfCircles(startingRingRadius, circleRadius); 

    //Let's get trivial cases out of the way 
    if (currentNumberOfCircles == 1) 
     return circleRadius; //trivial solution for 2 circles. 

    double centralAngle = 2 * Math.PI/(currentNumberOfCircles + 1); 
    return circleRadius/Math.Sin(centralAngle/2); 
} 

private static int GetCurrentNumberOfCircles(double startingRingRadius, double circleRadius) 
{ 
    if (startingRingRadius == 0) 
    { 
     return 1; 
    } 
    else 
    { 
     return (int)Math.Round(Math.PI/Math.Asin(circleRadius/startingRingRadius), 0); //There would need to be some logic to make sure input values are correct. 
    } 
} 

Для подтверждения ввода (определенные радиусы представляют действительное решение), вы можете сравнить округленное, а не округленное numberOfcircles и убедиться, что разница находится внутри данного допуска. Помните, что с double вы не можете проверить равенство, так как всегда будет ошибка представления.

UPDATE Огонь, я не видел, чтобы вы также спрашивали о расположении кругов. Как только вы знаете, что радиус кольца и центральный угол его довольно просты.

+0

Отлично. Спасибо! Прекрасно работает. У меня уже был код, чтобы сделать окончательное позиционирование кругов в моем вопросе, чтобы часть была излишней :) – Qubei

+0

@Qubei Добро пожаловать, рад, что это сработало. – InBetween