球体中心点和曲面上 3 个点的半径
Sphere center point and radius from 3 points on the surface
是否可以从曲面上的 3 个点求出球心和半径?
我正在为一个分段的大脑结构建立一个模型,如果三个点都在该结构内;头部、尾部和中间。
谢谢,
表示球心与给定三点等距且共面(假设给定三点在一个大圆上)
(X - Xa)² + (Y - Ya)² + (Z - Za)² = R²
(X - Xb)² + (Y - Yb)² + (Z - Zb)² = R²
(X - Xc)² + (Y - Yc)² + (Z - Zc)² = R²
|X Y Z 1|
|Xa Ya Za 1|
|Xb Yb Zb 1| = 0
|Xc Yc Zc 1|
用第二个和第三个方程减去第一个方程,你就去掉了二次项。
(2X - Xb - Xa)(Xb - Xa) + (2Y - Yb - Ya)(Yb - Ya) + (2Z - Zb - Za)(Zb - Za) = 0
(2X - Xc - Xa)(Xc - Xa) + (2Y - Yc - Ya)(Yc - Ya) + (2Z - Zc - Za)(Zc - Za) = 0
现在你有一个包含 3 个方程和 3 个未知数的简单线性系统。
为简洁起见,您可以将三个点翻译成Xa=Ya=Za=0
,方程式简化为
|X Y Z |
|Xb Yb Zb| = 0
|Xc Yc Zc|
(2X - Xb) Xb + (2Y - Yb) Yb + (2Z - Zb) Zb = 0
(2X - Xc) Xc + (2Y - Yc) Yc + (2Z - Zc) Zc = 0
或
(Yb Zc - Yc Zb) X + (Zb Xc - Zc Xb) Y + (Xb Yc - Xc Yb) Z = 0
2 Xb X + 2 Yb Y + 2 Zb Z = Xb² + Yb² + Zb²
2 Xc X + 2 Yc Y + 2 Zc Z = Xc² + Yc² + Zc²
那么,R² = X² + Y² + Z²
,别忘了翻译回来。
这确实是可能的,但它总是会给你一个球体,表面输入点将在它的赤道上(这意味着如果有第四个不共面的话,还有其他更大的球体在它的表面上有这 3 个点给分)。
但我认为最小的球体就是你想要的。以下用 C# 编写的代码为您提供了一个以球体为中心的 Vector3。然后可以使用任何输入点和结果中心之间的 Vector3.Distance(或简单的 pithagorean 距离)获得距离。
static public Vector3 BarycentricToWorld3D(Vector3 p1, Vector3 p2, Vector3 p3, float u, float v, float w) {
return (u * p1 + v * p2 + w * p3) / (u + v + w);
}
static public Vector3 CircleBariCenter3D(Vector3 p1, Vector3 p2, Vector3 p3) {
Vector3 a = p3 - p2;
Vector3 b = p1 - p3;
Vector3 c = p2 - p1;
float u = Vector3.Dot(a, a) * Vector3.Dot(c, b);
float v = Vector3.Dot(b, b) * Vector3.Dot(c, a);
float w = Vector3.Dot(c, c) * Vector3.Dot(b, a);
return BarycentricToWorld3D(p1, p2, p3, u, v, w);
}
请注意,没有检查共线点,这将导致失败。通过简单地输入这个共线点并在调试器中观察它失败来添加这样的检查应该是微不足道的。
致谢:我在 10 多年前获得了一个 maxscript 源代码,但丢失了原作者和位置,最近将其翻译成 C#。
是否可以从曲面上的 3 个点求出球心和半径?
我正在为一个分段的大脑结构建立一个模型,如果三个点都在该结构内;头部、尾部和中间。
谢谢,
表示球心与给定三点等距且共面(假设给定三点在一个大圆上)
(X - Xa)² + (Y - Ya)² + (Z - Za)² = R²
(X - Xb)² + (Y - Yb)² + (Z - Zb)² = R²
(X - Xc)² + (Y - Yc)² + (Z - Zc)² = R²
|X Y Z 1|
|Xa Ya Za 1|
|Xb Yb Zb 1| = 0
|Xc Yc Zc 1|
用第二个和第三个方程减去第一个方程,你就去掉了二次项。
(2X - Xb - Xa)(Xb - Xa) + (2Y - Yb - Ya)(Yb - Ya) + (2Z - Zb - Za)(Zb - Za) = 0
(2X - Xc - Xa)(Xc - Xa) + (2Y - Yc - Ya)(Yc - Ya) + (2Z - Zc - Za)(Zc - Za) = 0
现在你有一个包含 3 个方程和 3 个未知数的简单线性系统。
为简洁起见,您可以将三个点翻译成Xa=Ya=Za=0
,方程式简化为
|X Y Z |
|Xb Yb Zb| = 0
|Xc Yc Zc|
(2X - Xb) Xb + (2Y - Yb) Yb + (2Z - Zb) Zb = 0
(2X - Xc) Xc + (2Y - Yc) Yc + (2Z - Zc) Zc = 0
或
(Yb Zc - Yc Zb) X + (Zb Xc - Zc Xb) Y + (Xb Yc - Xc Yb) Z = 0
2 Xb X + 2 Yb Y + 2 Zb Z = Xb² + Yb² + Zb²
2 Xc X + 2 Yc Y + 2 Zc Z = Xc² + Yc² + Zc²
那么,R² = X² + Y² + Z²
,别忘了翻译回来。
这确实是可能的,但它总是会给你一个球体,表面输入点将在它的赤道上(这意味着如果有第四个不共面的话,还有其他更大的球体在它的表面上有这 3 个点给分)。
但我认为最小的球体就是你想要的。以下用 C# 编写的代码为您提供了一个以球体为中心的 Vector3。然后可以使用任何输入点和结果中心之间的 Vector3.Distance(或简单的 pithagorean 距离)获得距离。
static public Vector3 BarycentricToWorld3D(Vector3 p1, Vector3 p2, Vector3 p3, float u, float v, float w) {
return (u * p1 + v * p2 + w * p3) / (u + v + w);
}
static public Vector3 CircleBariCenter3D(Vector3 p1, Vector3 p2, Vector3 p3) {
Vector3 a = p3 - p2;
Vector3 b = p1 - p3;
Vector3 c = p2 - p1;
float u = Vector3.Dot(a, a) * Vector3.Dot(c, b);
float v = Vector3.Dot(b, b) * Vector3.Dot(c, a);
float w = Vector3.Dot(c, c) * Vector3.Dot(b, a);
return BarycentricToWorld3D(p1, p2, p3, u, v, w);
}
请注意,没有检查共线点,这将导致失败。通过简单地输入这个共线点并在调试器中观察它失败来添加这样的检查应该是微不足道的。
致谢:我在 10 多年前获得了一个 maxscript 源代码,但丢失了原作者和位置,最近将其翻译成 C#。