如何定位具有最大环半径的圆环

问题描述 投票:0回答:1

我正在尝试创建一个圆圈,唉:

这些圆有给定的半径,

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 InBetween's solution InBetween 解决方案的视觉确认

c# unity-game-engine 2d trigonometry unity3d-2dtools
1个回答
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
您无法检查是否相等,因为总会出现表示错误。

更新哎呀,我没看到你也在问关于定位圆圈的问题。一旦你知道了环半径和圆心角,它就非常简单了。

© www.soinside.com 2019 - 2024. All rights reserved.