计算 3D 平面圆的最小半径
Calculating the minimum radius for a circle of 3D planes
假设我们有 N
个 3D 卡片形平面围绕中心原点旋转,面向中间。
要计算这些平面的位置(相对于原点),我们使用以下内容:
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...
}
这很好用。但是现在,假设我们想要 ONLY 指定 N
,并用它来计算 Radius
,这样每个平面的边几乎没有接触,但没有碰撞.我们需要的是一种计算最小半径的方法。
我意识到我可以从一些高值开始,在一些 actor 中生成,检查它们是否发生碰撞,如果没有,然后移除所有 actor 并将 Radius
减少一些值,然后重新开始,直到我们发生碰撞,但这似乎有点矫枉过正。必须有一种更简单、更数学化的方法。
有什么想法吗?给定 ONLY n
(边数)和 a
(边宽),这里有一张图片可以帮助可视化我正在尝试计算的内容:
请注意,n = 6
和 a = 10
只是比喻性的例子。它们可以是任何非零值。
@KillzoneKid Updated question with my MSPaint skills to better
illustrate the current scenario
所以你想知道 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;
}
只需将多边形分成 same-size 个三角形(披萨片)并计算其中一个三角形 (Delta
) 的圆心角。给定三角形底边(周界边)的长度a
,用这个角度计算三角形的高。高度等于半径。
auto radius = a / FMath::Tan(Delta / 2.0);
要计算每个 "side" 中点的坐标,只需使用极坐标:
例如:
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);
}
假设我们有 N
个 3D 卡片形平面围绕中心原点旋转,面向中间。
要计算这些平面的位置(相对于原点),我们使用以下内容:
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...
}
这很好用。但是现在,假设我们想要 ONLY 指定 N
,并用它来计算 Radius
,这样每个平面的边几乎没有接触,但没有碰撞.我们需要的是一种计算最小半径的方法。
我意识到我可以从一些高值开始,在一些 actor 中生成,检查它们是否发生碰撞,如果没有,然后移除所有 actor 并将 Radius
减少一些值,然后重新开始,直到我们发生碰撞,但这似乎有点矫枉过正。必须有一种更简单、更数学化的方法。
有什么想法吗?给定 ONLY n
(边数)和 a
(边宽),这里有一张图片可以帮助可视化我正在尝试计算的内容:
请注意,n = 6
和 a = 10
只是比喻性的例子。它们可以是任何非零值。
@KillzoneKid Updated question with my MSPaint skills to better illustrate the current scenario
所以你想知道 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;
}
只需将多边形分成 same-size 个三角形(披萨片)并计算其中一个三角形 (Delta
) 的圆心角。给定三角形底边(周界边)的长度a
,用这个角度计算三角形的高。高度等于半径。
auto radius = a / FMath::Tan(Delta / 2.0);
要计算每个 "side" 中点的坐标,只需使用极坐标:
例如:
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);
}