문제

I am new to C# and XNA. Have just managed to write a class that generates a triangular grid. But there is one problem. I can get maximum 27 nodes length triangle. At 28 it throws Out of memory exception and at 31 -overFlow exception.

I don't understand how it overflows or out of memory... Tried to calculate all those memory values but they look very tiny.

It is only array of nodes affected by variable. Node class is not very big:

float x; 4 B float y; 4 B float z; 4 B int[] con; int[6] 4*6=24 B byte pass; 1 B Color col; 32 b= 4 B

            Total:  41B

sequence sum of nodes needed to create triangle is n(n+1)/2

out of memory at 28

28*29/2=406 nodes

total memory:

41*406 = 16646 B = 16.26 kB

Overflows at 31: 496 nodes is 19.9 kB

I did read articles about "out of memory exceptions", that structures size is bigger than it seems and that out of memory happens at sizes of 500MB... there is no way my small triangle would reach such huge size.

This is my whole class:

class TriMatrix
    {
        int len;
        int Lenght;
        Node[] node;
        VertexPositionColor[] vertex;

        public class Node
        {
            public float x;
            public float y;
            public float z;
            public int[] con;
            public byte pass;
            public Color col;
            public Node(byte passable)
            {
                pass = passable;
                if (pass > 0)
                { col = Color.Green; }
                else
                { col = Color.DarkRed; }
                x = 0;
                z = 0;
                con = new int[6];
            }
        }

        public TriMatrix(int lenght)
        {
            len = lenght;
            Lenght = 0;
            byte pass;
            Random rnd = new Random();
            for (int i = 0; i <= len; i++)
            {
                Lenght += Lenght + 1;
            }
            node = new Node[Lenght];
            int num = 0;
            for (int i = 0; i < len; i++)
            {
                for (int j = 0; j <= i; j++)
                {

                    if (rnd.Next(0, 5) > 0) { pass = 1; } else { pass = 0; }
                    node[num] = new Node(pass);
                    node[num].x = (float)i - (float)j / 2.0f;
                    node[num].y = 0;
                    node[num].z = (float)j * 0.6f;
                    if (i < len - 1) { node[num].con[0] = num + i; } else { node[num].con[0] = -1; node[num].col = Color.Violet; }
                    if (i < len - 1) { node[num].con[1] = num + i + 1; } else { node[num].con[1] = -1; }
                    if (j < i) { node[num].con[2] = num + 1; } else { node[num].con[2] = -1; node[num].col = Color.Violet; }
                    if (j < i) { node[num].con[3] = num - i; } else { node[num].con[3] = -1; }
                    if (i > 0) { node[num].con[4] = num - i - 1; } else { node[num].con[4] = -1; }
                    if (i > 0) { node[num].con[5] = num - 1; } else { node[num].con[5] = -1; }
                    if (j == 0) { node[num].col = Color.Violet; }
                    num++;
                }
            }
        }

        public void Draw(Effect effect, GraphicsDevice graphics)
        {
            VertexPositionColor[] verts = new VertexPositionColor[3];
            int num = 0;
            for (int i = 0; i < len-1; i++)
            {
                for (int j = 0; j <= i; j++)
                {
                    foreach (EffectPass pass in effect.CurrentTechnique.Passes)
                    {
                        pass.Apply();

                        verts[0] = new VertexPositionColor(new Vector3(node[num].x, node[num].y, node[num].z), node[num].col);
                        verts[1] = new VertexPositionColor(new Vector3(node[num + i + 1].x, node[num + i + 1].y, node[num + i + 1].z), node[num + i + 1].col);
                        verts[2] = new VertexPositionColor(new Vector3(node[num + i + 2].x, node[num + i + 2].y, node[num + i + 2].z), node[num + i + 2].col);
                        graphics.DrawUserPrimitives<VertexPositionColor>(PrimitiveType.TriangleStrip, verts, 0, 1);

                        if ( j < i)
                        {
                            verts[0] = new VertexPositionColor(new Vector3(node[num].x, node[num].y, node[num].z), node[num].col);
                            verts[1] = new VertexPositionColor(new Vector3(node[num + i + 2].x, node[num + i + 2].y, node[num + i + 2].z), node[num + i + 2].col);
                            verts[2] = new VertexPositionColor(new Vector3(node[num + 1].x, node[num + 1].y, node[num + 1].z), node[num + 1].col);
                            graphics.DrawUserPrimitives<VertexPositionColor>(PrimitiveType.TriangleStrip, verts, 0, 1);
                        }
                    }
                    num++;
                }
            }
        }
    }// endclass
도움이 되었습니까?

해결책

I assume that your bug lies in this loop (taking the liberty to correct your spelling):

for (int i = 0; i <= len; i++)
{
    Length += Length + 1;
}

Within the loop, you are incrementing the value of Length by itself plus one. This effectively means that you are doubling the value of Length for each iteration, resulting in exponential growth.

During the first few iterations, the values of Length will be: 1, 3, 7, 15, 31, 63, …. We can generalize this sequence such that, at iteration i, the value of Length will be 2i+1−1. At iteration 28, this would be 536,870,911. At iteration 31, this would be 4,294,967,295.

Edit: As you mentioned in the comment below, the correct fix for computing the number of elements in a triangular grid of length len would be:

for (int i = 1; i <= len; i++)
{
    Length += i;
} 

This is equivalent to the summation 1 + 2 + 3 + … + len, which computes what is known as the triangular number. It may be succinctly computed using the formula:

Length = len * (len + 1) / 2;

The reason that this number grows so large is that it is a square relation; for a side of length n, you need an area of approximately half of .

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top