代码之家  ›  专栏  ›  技术社区  ›  RectangleEquals

计算三维平面圆的最小半径

  •  3
  • RectangleEquals  · 技术社区  · 7 年前

    说我们有 N 围绕中心原点旋转、面向中间的三维卡片状平面的数量。 要计算这些平面的位置(相对于原点),我们使用以下公式:

    auto Delta = FMath::DegreesToRadians(360.f) / (float)(N);
    for (unsigned i = 0; i < N; i++) {
        auto X = Radius * FMath::Sin(Delta * (float)i);
        auto Y = Radius * FMath::Cos(Delta * (float)i);
        auto Location = FVector(X, Y, 0.f);
        // Spawn plane actor, set it's location, etc...
    }
    

    这很有效。但是现在,我们想 仅限 具体说明 N ,并使用它来计算 Radius 因此,每个平面的侧面几乎没有接触,但没有碰撞。我们需要的是一种计算最小半径的方法。

    我意识到我可以从一些高值开始,加入一些参与者,检查他们是否发生碰撞,如果没有,然后移除所有参与者并减少 半径 然后重新开始,直到发生碰撞,但这似乎有些过头了。必须有一种更简单、更数学的方法。

    有什么想法吗?这是一张图片,可以帮助我直观地计算 仅限 n (边数)和 a (侧面宽度):

    enter image description here

    请注意 n = 6 a = 10 只是一些象征性的例子。它们可以是任何非零值。

    2 回复  |  直到 7 年前
        1
  •  2
  •   Felix Glas    7 年前

    只需将多边形分成大小相同的三角形(披萨切片),然后计算其中一个三角形的中心角( Delta ). 给定三角形底的长度(周长边) a ,使用此角度计算三角形的高度。高度等于半径。

    auto radius = a / FMath::Tan(Delta / 2.0);
    

    要计算每个“边”中点的坐标,只需使用极坐标:

    Polar Coordinates

    例如。 :

    for (unsigned i = 0; i < N; i++) {
        /* ... */
        auto x = radius * FMath::Cos(i * Delta + Delta / 2.0);
        auto y = radius * FMath::Sin(i * Delta + Delta / 2.0);
    }
    
        2
  •  2
  •   Killzone Kid    7 年前

    @KillzoneKid用我的MSPaint技能更新了问题 说明当前场景

    所以你想知道X和Y把飞机放在哪里?半径已知时应该很容易。如果可行的话,可以尝试这样的方法(2D,但您可以将其调整为3D):

    #include <iostream>
    #include <cmath>
    
    int main() {
    
        constexpr double PI = 3.141592653589793238;
        double sideWidth = 248;
        int countSides = 6;
    
        double deltaAngleRads = 2.0 / countSides * PI;
        double minRadius = sideWidth / (2 * std::tan(PI / countSides));
    
        double rads = 0.0;
        for (int i = 0; i < countSides; ++i)
        {
            std::cout << "X=" << minRadius * std::sin(rads) << "\tY=" << minRadius * std::cos(rads) << std::endl;
            rads += deltaAngleRads;
        }
    
        std::cout << "Min radius: " << minRadius << std::endl;
    
        return 0;
    }
    

    https://ideone.com/zo0HV1