示例#1
0
    private static void test01()

    //****************************************************************************80
    //
    //  Purpose:
    //
    //    TEST01 tests the coordinate conversion routines.
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    15 December 2013
    //
    //  Author:
    //
    //    John Burkardt
    //
    {
        int m;

        Console.WriteLine("");
        Console.WriteLine("TEST01");
        Console.WriteLine("  Test the coordinate conversion routines:");
        Console.WriteLine("  CARTESIAN_TO_HYPERSPHERE: X       -> R,Theta");
        Console.WriteLine("  HYPERSPHERE_TO_CARTESIAN: R,Theta -> X.");
        Console.WriteLine("");
        Console.WriteLine("  Pick a random X, and compute X2 by converting X");
        Console.WriteLine("  to hypersphere and back.  Consider norm of difference.");
        Console.WriteLine("");
        Console.WriteLine("  M    || X - X2 ||");

        int seed = 123456789;

        const int n = 1;

        double[] r = new double[n];

        for (m = 1; m <= 5; m++)
        {
            Console.WriteLine("");

            double[] theta = new double[(m - 1) * n];

            int test;
            for (test = 1; test <= 5; test++)
            {
                double[] x = UniformRNG.r8mat_uniform_01_new(m, n, ref seed);
                double[] c = UniformRNG.r8vec_uniform_01_new(m, ref seed);
                Hypersphere.cartesian_to_hypersphere(m, n, c, x, ref r, ref theta);
                double[] x2  = Hypersphere.hypersphere_to_cartesian(m, n, c, r, theta);
                double   err = typeMethods.r8mat_norm_fro_affine(m, n, x, x2);
                Console.WriteLine("  " + m.ToString(CultureInfo.InvariantCulture).PadLeft(2)
                                  + "  " + err.ToString(CultureInfo.InvariantCulture).PadLeft(14) + "");
            }
        }
    }
示例#2
0
    public static double ellipsoid_volume(int m, double[] a, double[] v, double r)

    //****************************************************************************80
    //
    //  Purpose:
    //
    //    ELLIPSOID_VOLUME returns the volume of an ellipsoid.
    //
    //  Discussion:
    //
    //    The points X in the ellipsoid are described by an M by M
    //    positive definite symmetric matrix A, an M-dimensional point V,
    //    and a "radius" R, such that
    //      (X-V)' * A * (X-V) <= R * R
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    14 August 2014
    //
    //  Author:
    //
    //    John Burkardt
    //
    //  Parameters:
    //
    //    Input, int M, the spatial dimension.
    //
    //    Input, double A[M*M], the matrix that describes
    //    the ellipsoid.  A must be symmetric and positive definite.
    //
    //    Input, double V[M], the "center" of the ellipse.
    //    The value of V is not actually needed by this function.
    //
    //    Input, double R, the "radius" of the ellipse.
    //
    //    Output, double ELLIPSOID_VOLUME, the volume of the ellipsoid.
    //
    {
        int i;

        double[] u = typeMethods.r8po_fa(m, a);

        double sqrt_det = 1.0;

        for (i = 0; i < m; i++)
        {
            sqrt_det *= u[i + i * m];
        }

        double volume = Math.Pow(r, m) * Hypersphere.hypersphere_unit_volume(m) / sqrt_det;

        return(volume);
    }
示例#3
0
    private static void test06()

    //****************************************************************************80
    //
    //  Purpose:
    //
    //    TEST06 tests the stereographic mapping.
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    15 December 2013
    //
    //  Author:
    //
    //    John Burkardt
    //
    {
        int m;

        Console.WriteLine("");
        Console.WriteLine("TEST06");
        Console.WriteLine("  Test the stereographic mapping:");
        Console.WriteLine("  HYPERSPHERE_STEREOGRAPH maps hypersphere points to the plane.");
        Console.WriteLine("  HYPERSPHERE_STEREOGRAPH_INVERSE inverts the mapping.");
        Console.WriteLine("");
        Console.WriteLine("  Pick a random X1 on the hypersphere.");
        Console.WriteLine("  Map it to a point X2 on the plane.");
        Console.WriteLine("  Map it back to a point X3 on the hypersphere.");
        Console.WriteLine("  Consider norm of difference.");
        Console.WriteLine("");
        Console.WriteLine("  M    || X1 - X3 ||");

        int seed = 123456789;

        typeMethods.r8vecNormalData data = new();

        const int n = 1;

        for (m = 2; m <= 5; m++)
        {
            Console.WriteLine("");
            int test;
            for (test = 1; test <= 5; test++)
            {
                double[] x1  = Hypersphere.hypersphere_01_surface_uniform(m, n, ref data, ref seed);
                double[] x2  = Hypersphere.hypersphere_stereograph(m, n, x1);
                double[] x3  = Hypersphere.hypersphere_stereograph_inverse(m, n, x2);
                double   err = typeMethods.r8mat_norm_fro_affine(m, n, x1, x3);
                Console.WriteLine("  " + m.ToString(CultureInfo.InvariantCulture).PadLeft(2)
                                  + "  " + err.ToString(CultureInfo.InvariantCulture).PadLeft(14) + "");
            }
        }
    }
示例#4
0
    private static void test04()

    //****************************************************************************80
    //
    //  Purpose:
    //
    //    TEST04 tests HYPERSPHERE_01_VOLUME.
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    15 December 2013
    //
    //  Author:
    //
    //    John Burkardt
    //
    {
        int    m      = 0;
        double volume = 0;

        Console.WriteLine("");
        Console.WriteLine("TEST04:");
        Console.WriteLine("  HYPERSPHERE_01_VOLUME evaluates the area of the unit");
        Console.WriteLine("  hypersphere in M dimensions.");
        Console.WriteLine("  HYPERSPHERE_01_VOLUME_VALUES returns some test values.");
        Console.WriteLine("");
        Console.WriteLine("       M      Exact       Computed");
        Console.WriteLine("              Volume      Volume");
        Console.WriteLine("");

        int n_data = 0;

        for (;;)
        {
            Hypersphere.hypersphere_01_volume_values(ref n_data, ref m, ref volume);

            if (n_data == 0)
            {
                break;
            }

            double volume2 = Hypersphere.hypersphere_01_volume(m);

            Console.WriteLine("  " + m.ToString(CultureInfo.InvariantCulture).PadLeft(6)
                              + "  " + volume.ToString(CultureInfo.InvariantCulture).PadLeft(10)
                              + "  " + volume2.ToString(CultureInfo.InvariantCulture).PadLeft(10) + "");
        }
    }
示例#5
0
    private static void test03()

    //****************************************************************************80
    //
    //  Purpose:
    //
    //    TEST03 tests HYPERSPHERE_01_AREA.
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    15 December 2013
    //
    //  Author:
    //
    //    John Burkardt
    //
    {
        double area = 0;
        int    m    = 0;

        Console.WriteLine("");
        Console.WriteLine("TEST03:");
        Console.WriteLine("  HYPERSPHERE_01_AREA evaluates the area of the unit");
        Console.WriteLine("  hypersphere in M dimensions.");
        Console.WriteLine("");
        Console.WriteLine("       M      Exact       Computed");
        Console.WriteLine("              Area        Area");
        Console.WriteLine("");

        int n_data = 0;

        for (;;)
        {
            Hypersphere.hypersphere_01_area_values(ref n_data, ref m, ref area);

            if (n_data == 0)
            {
                break;
            }

            double area2 = Hypersphere.hypersphere_01_area(m);

            Console.WriteLine("  " + m.ToString(CultureInfo.InvariantCulture).PadLeft(6)
                              + "  " + area.ToString(CultureInfo.InvariantCulture).PadLeft(10)
                              + "  " + area2.ToString(CultureInfo.InvariantCulture).PadLeft(10) + "");
        }
    }
示例#6
0
    private static void test05()

    //****************************************************************************80
    //
    //  Purpose:
    //
    //    TEST05 tests HYPERSPHERE_AREA, HYPERSPHERE_VOLUME.
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    15 May 2013
    //
    //  Author:
    //
    //    John Burkardt
    //
    {
        int m;

        const double r = 1.5;

        Console.WriteLine("");
        Console.WriteLine("TEST05");
        Console.WriteLine("  For a hypersphere in M dimensions:");
        Console.WriteLine("  HYPERSPHERE_AREA computes the area");
        Console.WriteLine("  HYPERSPHERE_VOLUME computes the volume.");
        Console.WriteLine("");
        Console.WriteLine("  Notice that both quantities eventually decrease");
        Console.WriteLine("");
        Console.WriteLine("  We use a radius of R = " + r + "");
        Console.WriteLine("");
        Console.WriteLine("    M        Area          Volume    Area / Volume ");
        Console.WriteLine("");

        for (m = 1; m <= 20; m++)
        {
            double area   = Hypersphere.hypersphere_area(m, r);
            double volume = Hypersphere.hypersphere_volume(m, r);
            Console.WriteLine("  " + m.ToString(CultureInfo.InvariantCulture).PadLeft(3)
                              + "  " + area.ToString(CultureInfo.InvariantCulture).PadLeft(14)
                              + "  " + volume.ToString(CultureInfo.InvariantCulture).PadLeft(14)
                              + "  " + (area / volume).ToString(CultureInfo.InvariantCulture).PadLeft(14) + "");
        }
    }
示例#7
0
    private static void test02()

    //****************************************************************************80
    //
    //  Purpose:
    //
    //    TEST02 tests HYPERSPHERE_01_SURFACE_UNIFORM.
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    15 December 2013
    //
    //  Author:
    //
    //    John Burkardt
    //
    {
        int m;

        Console.WriteLine("");
        Console.WriteLine("TEST02");
        Console.WriteLine("  HYPERSPHERE_01_SURFACE_UNIFORM samples uniformly from the");
        Console.WriteLine("  surface of the unit hypersphere");

        int seed = 123456789;

        typeMethods.r8vecNormalData data = new();

        const int n = 1;

        for (m = 1; m <= 5; m++)
        {
            int test;
            for (test = 1; test <= 3; test++)
            {
                double[] x = Hypersphere.hypersphere_01_surface_uniform(m, n, ref data, ref seed);
                typeMethods.r8vec_transpose_print(m, x, "  Random hypersphere point:");
            }
        }
    }
示例#8
0
        static async Task Main(string[] args)
        {
            var surfaceSize  = new Size(640, 400);
            var pixelScaling = 3;
            var window       = new SdlWindow(surfaceSize * pixelScaling);
            var controls     = new Controls(window);

            var cameraPos   = Vector4.Zero;
            var cameraRot   = Matrix4.Identity;
            var focalLength = window.Height / 2.0f / pixelScaling;

            var circles = new Hypersphere[8];
            var rnd     = new Random(1);

            for (int i = 0; i < circles.Length; i++)
            {
                var w        = rnd.Next(-5.0f, 5.0f);
                var x        = rnd.Next(-12.0f, 12.0f);
                var y        = rnd.Next(-12.0f, 12.0f);
                var z        = rnd.Next(-12.0f, 12.0f);
                var position = Vector4.Forward * 16 + new Vector4(w, x, y, z);
                var radius   = rnd.Next(4.0f, 6.0f);
                circles[i] = new Hypersphere(position, radius);
            }

            window.Update += (delta) => {
                var mouseSensitivity = 0.2f;
                var moveSpeed        = 5.0f * (float)delta.TotalSeconds;

                if (controls.FourDimensionalMove)
                {
                    var roll = Deg2Rad(controls.MouseMotion.X) * mouseSensitivity;
                    var w    = Deg2Rad(controls.MouseMotion.Y) * mouseSensitivity;

                    var rollRot = new Matrix4(
                        1, 0, 0, 0,
                        0, Cos(roll), 0, -Sin(roll),
                        0, 0, 1, 0,
                        0, Sin(roll), 0, Cos(roll));

                    var wRot = new Matrix4(
                        Cos(w), 0, -Sin(w), 0,
                        0, 1, 0, 0,
                        Sin(w), 0, Cos(w), 0,
                        0, 0, 0, 1);

                    cameraRot = cameraRot * rollRot * wRot;

                    if (controls.Up)
                    {
                        cameraPos += cameraRot * Vector4.UnitW * moveSpeed;
                    }
                    if (controls.Down)
                    {
                        cameraPos += cameraRot * -Vector4.UnitW * moveSpeed;
                    }
                }

                if (controls.TraditionalMove)
                {
                    var yaw   = Deg2Rad(controls.MouseMotion.X) * mouseSensitivity;
                    var pitch = -Deg2Rad(controls.MouseMotion.Y) * mouseSensitivity;

                    var yawRot = new Matrix4(
                        1, 0, 0, 0,
                        0, Cos(yaw), -Sin(yaw), 0,
                        0, Sin(yaw), Cos(yaw), 0,
                        0, 0, 0, 1);

                    var pitchRot = new Matrix4(
                        1, 0, 0, 0,
                        0, 1, 0, 0,
                        0, 0, Cos(pitch), -Sin(pitch),
                        0, 0, Sin(pitch), Cos(pitch));

                    cameraRot = cameraRot * pitchRot * yawRot;

                    if (controls.Forward)
                    {
                        cameraPos += cameraRot * Vector4.Forward * moveSpeed;
                    }
                    if (controls.Back)
                    {
                        cameraPos += cameraRot * Vector4.Back * moveSpeed;
                    }
                    if (controls.Right)
                    {
                        cameraPos += cameraRot * Vector4.Right * moveSpeed;
                    }
                    if (controls.Left)
                    {
                        cameraPos += cameraRot * Vector4.Left * moveSpeed;
                    }
                    if (controls.Up)
                    {
                        cameraPos += cameraRot * Vector4.Up * moveSpeed;
                    }
                    if (controls.Down)
                    {
                        cameraPos += cameraRot * Vector4.Down * moveSpeed;
                    }
                }

                controls.ResetMouseMotion();
                return(Task.CompletedTask);
            };

            window.Render += async(delta) => {
                var forward   = cameraRot * Vector4.Forward;
                var stepRight = cameraRot * Vector4.Right;
                var stepDown  = cameraRot * Vector4.Down;

                var width  = window.Width / pixelScaling;
                var height = window.Height / pixelScaling;

                IEnumerable <Rectangle> SplitScreen(int size)
                {
                    for (var x = 0; x < width; x += size)
                    {
                        for (var y = 0; y < height; y += size)
                        {
                            yield return(new Rectangle(x, y, Math.Min(width, x + size), Math.Min(height, y + size)));
                        }
                    }
                }

                await Task.WhenAll(SplitScreen(32).Select(rect => Task.Run(() => {
                    var rayTmp = default(Ray);
                    var ray    = new Ray(cameraPos,
                                         forward *focalLength
                                         - stepRight * (width / 2 - rect.Left)
                                         - stepDown * (height / 2 - rect.Top));
                    for (var x = rect.Left; x < rect.Right; x++)
                    {
                        Vector4.Add(ref ray.Direction, stepRight);
                        rayTmp = ray;
                        for (var y = rect.Top; y < rect.Bottom; y++)
                        {
                            Vector4.Add(ref ray.Direction, stepDown);

                            float?tMin     = null;
                            int foundIndex = -1;
                            for (var i = 0; i < circles.Length; i++)
                            {
                                if ((circles[i].Intersect(ray) is float tCur) && !(tCur > tMin))
                                {
                                    tMin       = tCur;
                                    foundIndex = i;
                                }
                            }

                            if (tMin is float t)
                            {
                                var hit    = ray.Origin + ray.Direction *t;
                                var normal = circles[foundIndex].CalculateNormal(hit);
                                var color  = new Color(Math.Abs(normal.X), Math.Abs(normal.Y), Math.Abs(normal.Z));

                                for (var xx = 0; xx < pixelScaling; xx++)
                                {
                                    for (var yy = 0; yy < pixelScaling; yy++)
                                    {
                                        window.Surface[x *pixelScaling + xx, y *pixelScaling + yy] = color;
                                    }
                                }
                            }
                        }
                        ray = rayTmp;
                    }
                })));
            };

            await window.Run();
        }