【问题标题】:How to calculate the sphere center with 4 points?如何用 4 个点计算球心?
【发布时间】:2023-03-17 06:35:02
【问题描述】:

问题是我对编程很陌生,现在我需要编写一个程序来计算许多球体的中心(最大 36,最小 3),每个球体有 4 个点 X、Y、Z。因为我的程序读取了一个 TXT 文件,其中包含我将其存储在列表中的点数据,其结构如下

bolas[n].xyz[row,element]

这意味着我对球体 1 的第一组点是这样的:

bolas[0] = 
 row0.  -> [0] [1] [2]
 row1.  -> [0] [1] [2]
 row2.  -> [0] [1] [2]
 row3.  -> [0] [1] [2]

所以如果我想使用球体中第 1 行中 X 的值,我必须这样做:

bolas[0].xyz[0,0]

在网上搜索我发现有人转换了 java 代码并为 c# 实现它以计算球体的中心,他创建了一个类,但我很新,我不知道如何使用他的元素班级,我应该如何将我的数据引入他的班级以及如何获得结果;这是课程:

/// <summary>
/// Given four points in 3D space, solves for a sphere such that all four points
/// lie on the sphere's surface.
/// </summary>
/// <remarks>
/// Translated from Javascript on http://www.convertalot.com/sphere_solver.html, originally
/// linked to by http://stackoverflow.com/questions/13600739/calculate-centre-of-sphere-whose-surface-contains-4-points-c.
/// </remarks>
public class CircumcentreSolver
{
    private const float ZERO = 0;
    private double m_X0, m_Y0, m_Z0;
    private double m_Radius;
    private double[,] P = 
            {
                { ZERO, ZERO, ZERO },
                { ZERO, ZERO, ZERO },
                { ZERO, ZERO, ZERO },
                { ZERO, ZERO, ZERO }
            };

    /// <summary>
    /// The centre of the resulting sphere.
    /// </summary>
    public double[] Centre
    {
        get { return new double[] { this.m_X0, this.m_Y0, this.m_Z0 }; }
    }

    /// <summary>
    /// The radius of the resulting sphere.
    /// </summary>
    public double Radius
    {
        get { return this.m_Radius; }
    }

    /// <summary>
    /// Whether the result was a valid sphere.
    /// </summary>
    public bool Valid
    {
        get { return this.m_Radius != 0; }
    }

    /// <summary>
    /// Computes the centre of a sphere such that all four specified points in
    /// 3D space lie on the sphere's surface.
    /// </summary>
    /// <param name="a">The first point (array of 3 doubles for X, Y, Z).</param>
    /// <param name="b">The second point (array of 3 doubles for X, Y, Z).</param>
    /// <param name="c">The third point (array of 3 doubles for X, Y, Z).</param>
    /// <param name="d">The fourth point (array of 3 doubles for X, Y, Z).</param>
    public CircumcentreSolver(double[] a, double[] b, double[] c, double[] d)
    {
        this.Compute(a, b, c, d);
    }

    /// <summary>
    /// Evaluate the determinant.
    /// </summary>
    private void Compute(double[] a, double[] b, double[] c, double[] d)
    {
        P[0, 0] = a[0];
        P[0, 1] = a[1];
        P[0, 2] = a[2];
        P[1, 0] = b[0];
        P[1, 1] = b[1];
        P[1, 2] = b[2];
        P[2, 0] = c[0];
        P[2, 1] = c[1];
        P[2, 2] = c[2];
        P[3, 0] = d[0];
        P[3, 1] = d[1];
        P[3, 2] = d[2];

        // Compute result sphere.
        this.Sphere();
    }

    private void Sphere()
    {
        double r, m11, m12, m13, m14, m15;
        double[,] a =
                {
                    { ZERO, ZERO, ZERO, ZERO },
                    { ZERO, ZERO, ZERO, ZERO },
                    { ZERO, ZERO, ZERO, ZERO },
                    { ZERO, ZERO, ZERO, ZERO }
                };

        // Find minor 1, 1.
        for (int i = 0; i < 4; i++)
        {
            a[i, 0] = P[i, 0];
            a[i, 1] = P[i, 1];
            a[i, 2] = P[i, 2];
            a[i, 3] = 1;
        }
        m11 = this.Determinant(a, 4);

        // Find minor 1, 2.
        for (int i = 0; i < 4; i++)
        {
            a[i, 0] = P[i, 0] * P[i, 0] + P[i, 1] * P[i, 1] + P[i, 2] * P[i, 2];
            a[i, 1] = P[i, 1];
            a[i, 2] = P[i, 2];
            a[i, 3] = 1;
        }
        m12 = this.Determinant(a, 4);

        // Find minor 1, 3.
        for (int i = 0; i < 4; i++)
        {
            a[i, 0] = P[i, 0] * P[i, 0] + P[i, 1] * P[i, 1] + P[i, 2] * P[i, 2];
            a[i, 1] = P[i, 0];
            a[i, 2] = P[i, 2];
            a[i, 3] = 1;
        }
        m13 = this.Determinant(a, 4);

        // Find minor 1, 4.
        for (int i = 0; i < 4; i++)
        {
            a[i, 0] = P[i, 0] * P[i, 0] + P[i, 1] * P[i, 1] + P[i, 2] * P[i, 2];
            a[i, 1] = P[i, 0];
            a[i, 2] = P[i, 1];
            a[i, 3] = 1;
        }
        m14 = this.Determinant(a, 4);

        // Find minor 1, 5.
        for (int i = 0; i < 4; i++)
        {
            a[i, 0] = P[i, 0] * P[i, 0] + P[i, 1] * P[i, 1] + P[i, 2] * P[i, 2];
            a[i, 1] = P[i, 0];
            a[i, 2] = P[i, 1];
            a[i, 3] = P[i, 2];
        }
        m15 = this.Determinant(a, 4);

        // Calculate result.
        if (m11 == 0)
        {
            this.m_X0 = 0;
            this.m_Y0 = 0;
            this.m_Z0 = 0;
            this.m_Radius = 0;
        }
        else
        {
            this.m_X0 = 0.5 * m12 / m11;
            this.m_Y0 = -0.5 * m13 / m11;
            this.m_Z0 = 0.5 * m14 / m11;
            this.m_Radius = System.Math.Sqrt(this.m_X0 * this.m_X0 + this.m_Y0 * this.m_Y0 + this.m_Z0 * this.m_Z0 - m15 / m11);
        }
    }

    /// <summary>
    /// Recursive definition of determinate using expansion by minors.
    /// </summary>
    private double Determinant(double[,] a, double n)
    {
        int i, j, j1, j2;
        double d = 0;
        double[,] m = 
                {
                    { ZERO, ZERO, ZERO, ZERO },
                    { ZERO, ZERO, ZERO, ZERO },
                    { ZERO, ZERO, ZERO, ZERO },
                    { ZERO, ZERO, ZERO, ZERO }
                };

        if (n == 2)
        {
            // Terminate recursion.
            d = a[0, 0] * a[1, 1] - a[1, 0] * a[0, 1];
        }
        else
        {
            d = 0;
            for (j1 = 0; j1 < n; j1++) // Do each column.
            {
                for (i = 1; i < n; i++) // Create minor.
                {
                    j2 = 0;
                    for (j = 0; j < n; j++)
                    {
                        if (j == j1) continue;
                        m[i - 1, j2] = a[i, j];
                        j2++;
                    }
                }

                // Sum (+/-)cofactor * minor.
                d = d + System.Math.Pow(-1.0, j1) * a[0, j1] * this.Determinant(m, n - 1);
            }
        }

        return d;
    }
}

我怎么说我的数据球体编号可能会有所不同,但我最多有 36 个球体,每个球体有 4 个点 x、y、z。 如果我可以将结果中心存储在另一个列表中,这将非常有用,可能类似于:

ballCent[0]=
center-> [0][1][2] //center of the sphere[x][y][z].
radius-> [0]       //radius of the sphere.

我希望我解释得足够清楚,我不是以英语为母语的人,我非常感谢社区的帮助。 PS。我个人用我的数据尝试了该程序的 java 版本,它对我来说非常完美。 链接在这里: http://www.convertalot.com/sphere_solver.html

【问题讨论】:

  • 这不是一项简单的任务。您基本上必须解决具有 4 个变量和 4 个方程的非线性系统。您需要先研究如何解决该问题。
  • 在 Internet 中查找代码并简单地尝试使其工作而不尝试理解它绝对不是要走的路。
  • 忘记编码,你将如何手动解决这个问题?如果您不知道如何手动完成,那么您如何假装编写一个有效的算法?一旦您知道如何手动执行此操作,您就可以开始考虑如何对其进行编程以及需要哪些工具。没有人会在这里为你做你的工作。
  • @InBetween 你弄错了,我知道如何手动解决它,我知道它是如何工作的,我真正的问题是编码,正如我所说,我对编码真的很陌生不知道如何对算法进行编程,方便地我找到了我在那里展示的代码,我已经在 java 中测试过,但是有些人在 c# 上实现了,我的问题是这东西是如何工作的?我的意思是它只是一个函数的类吗?代码正文中有一些参数作为输入,然后它返回我的计算,我猜,但我真的不知道如何......只需要一个解释。谢谢。
  • 好,那么你的问题是你几乎没有学习如何编码。也许你应该从学习如何编写更简单的问题开始,你不能指望一帆风顺。这不是任何人都可以帮助您学习如何编码的地方。为此,您需要阅读书籍、学习、寻找导师等。如果您无法理解您粘贴的代码,甚至无法识别它是函数、类还是两者等等,那么您就是真的超出了你的深度,你应该退后一步,先学习基础知识。这是我的建议。

标签: c# class math determinants


【解决方案1】:

使用前两点定义一条线。对后两个做同样的事情。找到两条线之间的 POI。

【讨论】:

  • 在三维空间中,两点之间的等距范围是一个平面,而不是一条线。
  • @EdwardPeters 你在说什么?在任何维度空间中,两点之间都有一条明确的线......
  • 它们之间的线定义明确,但没有用。 (没有理由球的中心会在那条线上,或者你描述的两条线会相交。)相反,你想考虑 equidistant 的点集 - 因为与 4 个输入点等距的点将是球体的中心。
  • 假设球体是地球,点是北极、南极、纽约和波士顿。从北极到南极的线不与从纽约到波士顿的线相交。此外,如果我以我家方形地基的角为 4 个点,那么对角线之间的线相交,但不靠近中心。编辑:在你有机会编辑之前写了这个。留在这里留给后人。 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-02-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多