Why is my marching cubes algorythm leaving holes behind? - c#
I just made a marching cubes algorythm and after 2 days i saw some holes in the mesh.
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
public class MarchinCubes : MonoBehaviour
{
public int size = 1;
public float surfaceValue = .5f;
public int xOffset = 0;
public int yOffset = 0;
public int zOffset = 0;
public float zoom = 1;
public bool interpolation;
public bool shading;
public bool autoUpdate;
public bool sphereValues;
void Start()
{
xOffset = (int)transform.position.x;
yOffset = (int)transform.position.y;
zOffset = (int)transform.position.z;
Starter();
}
void Update()
{
if (Input.GetKeyDown(KeyCode.U) || autoUpdate)
{
xOffset = (int)transform.position.x;
yOffset = (int)transform.position.y;
zOffset = (int)transform.position.z;
Starter();
Vector3 position = transform.position;
Vector3 newPosition = new Vector3(Mathf.Floor(position.x), Mathf.Floor(position.y), Mathf.Floor(position.z));
transform.position = newPosition;
}
}
void Starter()
{
int pointSize = size + 1;
float[][][] values = sphereValues ? sphere(pointSize) : Perlin(pointSize);
Mesh mesh = CreateMesh(values, pointSize - 1);
mesh.RecalculateNormals();
GetComponent<MeshFilter>().mesh = mesh;
}
float[][][] sphere(int size)
{
float[][][] values = initializeFloatArray(size);
for (int x = 0; x < size; x++)
{
for (int y = 0; y < size; y++)
{
for (int z = 0; z < size; z++)
{
values[x][y][z] = 10 - distance(x, y, z, size / 2, size / 2, size / 2);
}
}
}
return values;
}
float distance(float x, float y, float z, float xCenter, float yCenter, float zCenter)
{
return Mathf.Sqrt(Mathf.Pow(x - xCenter, 2) + Mathf.Pow(y - yCenter, 2) + Mathf.Pow(z - zCenter, 2));
}
float[][][] Perlin(int size)
{
float[][][] values = initializeFloatArray(size);
for (int x = 0; x < size; x++)
{
for (int y = 0; y < size; y++)
{
for (int z = 0; z < size; z++)
{
if (x == 0 || x == size - 1 || y == 0 || y == size - 1 ||z == 0 || z == size - 1)
{
values[x][y][z] = 0;
}
else
{
values[x][y][z] = (GetPerlin(x, y, z, 40f) + GetPerlin(x, y, z, 20f)) / 2;
}
}
}
}
return values;
}
float GetPerlin(int xInt, int yInt, int zInt, float divider)
{
float z = (zInt + zOffset) / divider;
float y = (yInt + yOffset) / divider;
float x = (xInt + xOffset) / divider;
float zy = Mathf.PerlinNoise(x, y);
float zx = Mathf.PerlinNoise(x, z);
float yx = Mathf.PerlinNoise(y, z);
float yz = Mathf.PerlinNoise(y, x);
float xz = Mathf.PerlinNoise(z, x);
float xy = Mathf.PerlinNoise(z, y);
return (xy + xz + yz + yx + zx + zy) / 6;
}
float[][][] initializeFloatArray(int size)
{
float[][][] values = new float[size][][];
for (int x = 0; x < size; x++)
{
values[x] = new float[size][];
for (int i = 0; i < size; i++)
{
values[x][i] = new float[size];
}
}
return values;
}
Mesh CreateMesh(float[][][] values, int size)
{
Vector3[] vertices = initializeVector3Array(size * 2 + 1, size * 2 + 1, size * 2 + 1);
int[] triangles = new int[size * size * size * 3 * 2];
Mesh mesh = new Mesh();
int triangleCount = 0;
for (int x = 0; x < size; x++)
{
for (int y = 0; y < size; y++)
{
for (int z = 0; z < size; z++)
{
int[] triangleTable = table[getTriangleIndex(
new[] {
values[x][y][z],
values[x + 1][y][z],
values[x + 1][y][z + 1],
values[x][y][z + 1],
values[x][y + 1][z],
values[x + 1][y + 1][z],
values[x + 1][y + 1][z + 1],
values[x][y + 1][z + 1]
},
surfaceValue)];
int[] trianglesToAdd = new int[triangleTable.Length];
for (int i = 0; i < triangleTable.Length; i += 3)
{
trianglesToAdd[i] = getVertexIndex(x, y, z, triangleTable[i], size * 2 + 2);
trianglesToAdd[i + 1] = getVertexIndex(x, y, z, triangleTable[i + 1], size * 2 + 2);
trianglesToAdd[i + 2] = getVertexIndex(x, y, z, triangleTable[i + 2], size * 2 + 2);
}
for (int i = 0; i < trianglesToAdd.Length; i++)
{
triangles[triangleCount] = trianglesToAdd[i];
triangleCount++;
}
}
}
}
if (interpolation)
{
vertices = addIndterpolation(vertices, size * 2 + 2, values, surfaceValue);
}
vertices = ScaleVertices(vertices);
if (shading == false)
{
RemakeMeshToDiscrete(vertices, triangles, out vertices, out triangles);
}
mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32;
mesh.vertices = vertices;
mesh.triangles = triangles;
return mesh;
}
Vector3[] ScaleVertices(Vector3[] vertices)
{
for (int i = 0; i < vertices.Length; i++)
{
vertices[i].x = vertices[i].x / transform.localScale.x;
vertices[i].y = vertices[i].y / transform.localScale.y;
vertices[i].z = vertices[i].z / transform.localScale.z;
}
return vertices;
}
void RemakeMeshToDiscrete(Vector3[] vert, int[] trig, out Vector3[] outVertices, out int[] outTriangles)
{
Vector3[] vertDiscrete = new Vector3[trig.Length];
int[] trigDiscrete = new int[trig.Length];
for (int i = 0; i < trig.Length; i++)
{
vertDiscrete[i] = vert[trig[i]];
trigDiscrete[i] = i;
}
outVertices = vertDiscrete;
outTriangles = trigDiscrete;
}
Vector3[] addIndterpolation(Vector3[] array, int sizeVertices, float[][][] values, float surfaceValue)
{
int sizeValues = values.Length;
for (int x = 0; x < sizeValues - 1; x++)
{
for (int y = 0; y < sizeValues - 1; y++)
{
for (int z = 0; z < sizeValues - 1; z++)
{
int arrayCords = z * 2 + y * sizeVertices * 2 + x * sizeVertices * sizeVertices * 2;
float value = values[x][y][z];
float valueZ = values[x + 1][y][z];
float valueY = values[x][y + 1][z];
float valueX = values[x][y][z + 1];
float interpolationValueX = Mathf.Abs(surfaceValue - value) / (Mathf.Abs(surfaceValue - value) + Mathf.Abs(surfaceValue - valueX));
float interpolationValueY = Mathf.Abs(surfaceValue - value) / (Mathf.Abs(surfaceValue - value) + Mathf.Abs(surfaceValue - valueY));
float interpolationValueZ = Mathf.Abs(surfaceValue - value) / (Mathf.Abs(surfaceValue - value) + Mathf.Abs(surfaceValue - valueZ));
array[arrayCords + 1] += new Vector3(0, 0, interpolationValueX - .5f);
array[arrayCords + sizeVertices] += new Vector3(0, interpolationValueY - .5f, 0);
array[arrayCords + sizeVertices * sizeVertices] += new Vector3(interpolationValueZ - .5f, 0, 0);
}
}
}
return array;
}
int getVertexIndex(int z, int y, int x, int cubeValue, int size)
{
int[][] vertecieValues = new[] {
new []{1, 0, 0 },
new []{2, 0, 1 },
new []{1, 0, 2 },
new []{0, 0, 1 },
new []{1, 2, 0 },
new []{2, 2, 1 },
new []{1, 2, 2 },
new []{0, 2, 1 },
new []{0, 1, 0 },
new []{2, 1, 0 },
new []{2, 1, 2 },
new []{0, 1, 2 }
};
int xReturn = z * 2 * size * size;
int yReturn = y * 2 * size;
int zReturn = x * 2;
return xReturn + vertecieValues[cubeValue][0] * size * size + yReturn + vertecieValues[cubeValue][1] * size + zReturn + vertecieValues[cubeValue][2];
}
int getTriangleIndex(float[] values, float surfaceValue)
{
int index = 0;
for (int i = 0; i < 8; i++)
{
if (values[i] > surfaceValue)
{
index |= 1 << i;
}
}
return index;
}
Vector3[] initializeVector3Array(int Xsize, int Ysize, int Zsize)
{
Vector3[] array = new Vector3[(Xsize + 1) * (Ysize + 1) * (Zsize + 1)];
int count = 0;
for (int x = 0; x < Xsize + 1; x++)
{
for (int y = 0; y < Ysize + 1; y++)
{
for (int z = 0; z < Zsize + 1; z++)
{
array[count] = new Vector3(x / 2f, y / 2f, z / 2f);
count++;
}
}
}
return array;
}
int[][] table = new int[][] {
new int[] { },
new int[] { 8, 3, 0},
new int[] { 9, 0, 1},
new int[] { 8, 3, 1, 8, 1, 9},
new int[] {10, 1, 2},
new int[] { 8, 3, 0, 1, 2,10},
new int[] { 9, 0, 2, 9, 2,10},
new int[] { 3, 2, 8, 2,10, 8, 8,10, 9},
new int[] {11, 2, 3},
new int[] {11, 2, 0,11, 0, 8},
new int[] {11, 2, 3, 0, 1, 9},
new int[] { 2, 1,11, 1, 9,11,11, 9, 8},
new int[] {10, 1, 3,10, 3,11},
new int[] { 1, 0,10, 0, 8,10,10, 8,11},
new int[] { 0, 3, 9, 3,11, 9, 9,11,10},
new int[] { 8,10, 9, 8,11,10},
new int[] { 8, 4, 7},
new int[] { 3, 0, 4, 3, 4, 7},
new int[] { 1, 9, 0, 8, 4, 7},
new int[] { 9, 4, 1, 4, 7, 1, 1, 7, 3},
new int[] {10, 1, 2, 8, 4, 7},
new int[] { 2,10, 1, 0, 4, 7, 0, 7, 3},
new int[] { 4, 7, 8, 0, 2,10, 0,10, 9},
new int[] { 2, 7, 3, 2, 9, 7, 7, 9, 4, 2,10, 9},
new int[] { 2, 3,11, 7, 8, 4},
new int[] { 7,11, 4,11, 2, 4, 4, 2, 0},
new int[] { 3,11, 2, 4, 7, 8, 9, 0, 1},
new int[] { 2, 7,11, 2, 1, 7, 1, 4, 7, 1, 9, 4},
new int[] { 8, 4, 7,11,10, 1,11, 1, 3},
new int[] {11, 4, 7, 1, 4,11, 1,11,10, 1, 0, 4},
new int[] { 3, 8, 0, 7,11, 4,11, 9, 4,11,10, 9},
new int[] { 7,11, 4, 4,11, 9,11,10, 9},
new int[] { 9, 5, 4},
new int[] { 3, 0, 8, 4, 9, 5},
new int[] { 5, 4, 0, 5, 0, 1},
new int[] { 4, 8, 5, 8, 3, 5, 5, 3, 1},
new int[] { 2,10, 1, 9, 5, 4},
new int[] { 0, 8, 3, 5, 4, 9,10, 1, 2},
new int[] {10, 5, 2, 5, 4, 2, 2, 4, 0},
new int[] { 3, 4, 8, 3, 2, 4, 2, 5, 4, 2,10, 5},
new int[] {11, 2, 3, 9, 5, 4},
new int[] { 9, 5, 4, 8,11, 2, 8, 2, 0},
new int[] { 3,11, 2, 1, 5, 4, 1, 4, 0},
new int[] { 8, 5, 4, 2, 5, 8, 2, 8,11, 2, 1, 5},
new int[] { 5, 4, 9, 1, 3,11, 1,11,10},
new int[] { 0, 9, 1, 4, 8, 5, 8,10, 5, 8,11,10},
new int[] { 3, 4, 0, 3,10, 4, 4,10, 5, 3,11,10},
new int[] { 4, 8, 5, 5, 8,10, 8,11,10},
new int[] { 9, 5, 7, 9, 7, 8},
new int[] { 0, 9, 3, 9, 5, 3, 3, 5, 7},
new int[] { 8, 0, 7, 0, 1, 7, 7, 1, 5},
new int[] { 1, 7, 3, 1, 5, 7},
new int[] { 1, 2,10, 5, 7, 8, 5, 8, 9},
new int[] { 9, 1, 0,10, 5, 2, 5, 3, 2, 5, 7, 3},
new int[] { 5, 2,10, 8, 2, 5, 8, 5, 7, 8, 0, 2},
new int[] {10, 5, 2, 2, 5, 3, 5, 7, 3},
new int[] {11, 2, 3, 8, 9, 5, 8, 5, 7},
new int[] { 9, 2, 0, 9, 7, 2, 2, 7,11, 9, 5, 7},
new int[] { 0, 3, 8, 2, 1,11, 1, 7,11, 1, 5, 7},
new int[] { 2, 1,11,11, 1, 7, 1, 5, 7},
new int[] { 3, 9, 1, 3, 8, 9, 7,11,10, 7,10, 5},
new int[] { 9, 1, 0,10, 7,11,10, 5, 7},
new int[] { 3, 8, 0, 7,10, 5, 7,11,10},
new int[] {11, 5, 7,11,10, 5},
new int[] {10, 6, 5},
new int[] { 8, 3, 0,10, 6, 5},
new int[] { 0, 1, 9, 5,10, 6},
new int[] {10, 6, 5, 9, 8, 3, 9, 3, 1},
new int[] { 1, 2, 6, 1, 6, 5},
new int[] { 0, 8, 3, 2, 6, 5, 2, 5, 1},
new int[] { 5, 9, 6, 9, 0, 6, 6, 0, 2},
new int[] { 9, 6, 5, 3, 6, 9, 3, 9, 8, 3, 2, 6},
new int[] { 3,11, 2,10, 6, 5},
new int[] { 6, 5,10, 2, 0, 8, 2, 8,11},
new int[] { 1, 9, 0, 6, 5,10,11, 2, 3},
new int[] { 1,10, 2, 5, 9, 6, 9,11, 6, 9, 8,11},
new int[] {11, 6, 3, 6, 5, 3, 3, 5, 1},
new int[] { 0, 5, 1, 0,11, 5, 5,11, 6, 0, 8,11},
new int[] { 0, 5, 9, 0, 3, 5, 3, 6, 5, 3,11, 6},
new int[] { 5, 9, 6, 6, 9,11, 9, 8,11},
new int[] {10, 6, 5, 4, 7, 8},
new int[] { 5,10, 6, 7, 3, 0, 7, 0, 4},
new int[] { 5,10, 6, 0, 1, 9, 8, 4, 7},
new int[] { 4, 5, 9, 6, 7,10, 7, 1,10, 7, 3, 1},
new int[] { 7, 8, 4, 5, 1, 2, 5, 2, 6},
new int[] { 4, 1, 0, 4, 5, 1, 6, 7, 3, 6, 3, 2},
new int[] { 9, 4, 5, 8, 0, 7, 0, 6, 7, 0, 2, 6},
new int[] { 4, 5, 9, 6, 3, 2, 6, 7, 3},
new int[] { 7, 8, 4, 2, 3,11,10, 6, 5},
new int[] {11, 6, 7,10, 2, 5, 2, 4, 5, 2, 0, 4},
new int[] {11, 6, 7, 8, 0, 3, 1,10, 2, 9, 4, 5},
new int[] { 6, 7,11, 1,10, 2, 9, 4, 5},
new int[] { 6, 7,11, 4, 5, 8, 5, 3, 8, 5, 1, 3},
new int[] { 6, 7,11, 4, 1, 0, 4, 5, 1},
new int[] { 4, 5, 9, 3, 8, 0,11, 6, 7},
new int[] { 9, 4, 5, 7,11, 6},
new int[] {10, 6, 4,10, 4, 9},
new int[] { 8, 3, 0, 9,10, 6, 9, 6, 4},
new int[] { 1,10, 0,10, 6, 0, 0, 6, 4},
new int[] { 8, 6, 4, 8, 1, 6, 6, 1,10, 8, 3, 1},
new int[] { 9, 1, 4, 1, 2, 4, 4, 2, 6},
new int[] { 1, 0, 9, 3, 2, 8, 2, 4, 8, 2, 6, 4},
new int[] { 2, 4, 0, 2, 6, 4},
new int[] { 3, 2, 8, 8, 2, 4, 2, 6, 4},
new int[] { 2, 3,11, 6, 4, 9, 6, 9,10},
new int[] { 0,10, 2, 0, 9,10, 4, 8,11, 4,11, 6},
new int[] {10, 2, 1,11, 6, 3, 6, 0, 3, 6, 4, 0},
new int[] {10, 2, 1,11, 4, 8,11, 6, 4},
new int[] { 1, 4, 9,11, 4, 1,11, 1, 3,11, 6, 4},
new int[] { 0, 9, 1, 4,11, 6, 4, 8,11},
new int[] {11, 6, 3, 3, 6, 0, 6, 4, 0},
new int[] { 8, 6, 4, 8,11, 6},
new int[] { 6, 7,10, 7, 8,10,10, 8, 9},
new int[] { 9, 3, 0, 6, 3, 9, 6, 9,10, 6, 7, 3},
new int[] { 6, 1,10, 6, 7, 1, 7, 0, 1, 7, 8, 0},
new int[] { 6, 7,10,10, 7, 1, 7, 3, 1},
new int[] { 7, 2, 6, 7, 9, 2, 2, 9, 1, 7, 8, 9},
new int[] { 1, 0, 9, 3, 6, 7, 3, 2, 6},
new int[] { 8, 0, 7, 7, 0, 6, 0, 2, 6},
new int[] { 2, 7, 3, 2, 6, 7},
new int[] { 7,11, 6, 3, 8, 2, 8,10, 2, 8, 9,10},
new int[] {11, 6, 7,10, 0, 9,10, 2, 0},
new int[] { 2, 1,10, 7,11, 6, 8, 0, 3},
new int[] { 1,10, 2, 6, 7,11},
new int[] { 7,11, 6, 3, 9, 1, 3, 8, 9},
new int[] { 9, 1, 0,11, 6, 7},
new int[] { 0, 3, 8,11, 6, 7},
new int[] {11, 6, 7},
new int[] {11, 7, 6},
new int[] { 0, 8, 3,11, 7, 6},
new int[] { 9, 0, 1,11, 7, 6},
new int[] { 7, 6,11, 3, 1, 9, 3, 9, 8},
new int[] { 1, 2,10, 6,11, 7},
new int[] { 2,10, 1, 7, 6,11, 8, 3, 0},
new int[] {11, 7, 6,10, 9, 0,10, 0, 2},
new int[] { 7, 6,11, 3, 2, 8, 8, 2,10, 8,10, 9},
new int[] { 2, 3, 7, 2, 7, 6},
new int[] { 8, 7, 0, 7, 6, 0, 0, 6, 2},
new int[] { 1, 9, 0, 3, 7, 6, 3, 6, 2},
new int[] { 7, 6, 2, 7, 2, 9, 2, 1, 9, 7, 9, 8},
new int[] { 6,10, 7,10, 1, 7, 7, 1, 3},
new int[] { 6,10, 1, 6, 1, 7, 7, 1, 0, 7, 0, 8},
new int[] { 9, 0, 3, 6, 9, 3, 6,10, 9, 6, 3, 7},
new int[] { 6,10, 7, 7,10, 8,10, 9, 8},
new int[] { 8, 4, 6, 8, 6,11},
new int[] {11, 3, 6, 3, 0, 6, 6, 0, 4},
new int[] { 0, 1, 9, 4, 6,11, 4,11, 8},
new int[] { 1, 9, 4,11, 1, 4,11, 3, 1,11, 4, 6},
new int[] {10, 1, 2,11, 8, 4,11, 4, 6},
new int[] {10, 1, 2,11, 3, 6, 6, 3, 0, 6, 0, 4},
new int[] { 0, 2,10, 0,10, 9, 4,11, 8, 4, 6,11},
new int[] { 2,11, 3, 6, 9, 4, 6,10, 9},
new int[] { 3, 8, 2, 8, 4, 2, 2, 4, 6},
new int[] { 2, 0, 4, 2, 4, 6},
new int[] { 1, 9, 0, 3, 8, 2, 2, 8, 4, 2, 4, 6},
new int[] { 9, 4, 1, 1, 4, 2, 4, 6, 2},
new int[] { 8, 4, 6, 8, 6, 1, 6,10, 1, 8, 1, 3},
new int[] { 1, 0,10,10, 0, 6, 0, 4, 6},
new int[] { 8, 0, 3, 9, 6,10, 9, 4, 6},
new int[] {10, 4, 6,10, 9, 4},
new int[] { 9, 5, 4, 7, 6,11},
new int[] { 4, 9, 5, 3, 0, 8,11, 7, 6},
new int[] { 6,11, 7, 4, 0, 1, 4, 1, 5},
new int[] { 6,11, 7, 4, 8, 5, 5, 8, 3, 5, 3, 1},
new int[] { 6,11, 7, 1, 2,10, 9, 5, 4},
new int[] {11, 7, 6, 8, 3, 0, 1, 2,10, 9, 5, 4},
new int[] {11, 7, 6,10, 5, 2, 2, 5, 4, 2, 4, 0},
new int[] { 7, 4, 8, 2,11, 3,10, 5, 6},
new int[] { 4, 9, 5, 6, 2, 3, 6, 3, 7},
new int[] { 9, 5, 4, 8, 7, 0, 0, 7, 6, 0, 6, 2},
new int[] { 4, 0, 1, 4, 1, 5, 6, 3, 7, 6, 2, 3},
new int[] { 7, 4, 8, 5, 2, 1, 5, 6, 2},
new int[] { 4, 9, 5, 6,10, 7, 7,10, 1, 7, 1, 3},
new int[] { 5, 6,10, 0, 9, 1, 8, 7, 4},
new int[] { 5, 6,10, 7, 0, 3, 7, 4, 0},
new int[] {10, 5, 6, 4, 8, 7},
new int[] { 5, 6, 9, 6,11, 9, 9,11, 8},
new int[] { 0, 9, 5, 0, 5, 3, 3, 5, 6, 3, 6,11},
new int[] { 0, 1, 5, 0, 5,11, 5, 6,11, 0,11, 8},
new int[] {11, 3, 6, 6, 3, 5, 3, 1, 5},
new int[] { 1, 2,10, 5, 6, 9, 9, 6,11, 9,11, 8},
new int[] { 1, 0, 9, 6,10, 5,11, 3, 2},
new int[] { 6,10, 5, 2, 8, 0, 2,11, 8},
new int[] { 3, 2,11,10, 5, 6},
new int[] { 9, 5, 6, 3, 9, 6, 3, 8, 9, 3, 6, 2},
new int[] { 5, 6, 9, 9, 6, 0, 6, 2, 0},
new int[] { 0, 3, 8, 2, 5, 6, 2, 1, 5},
new int[] { 1, 6, 2, 1, 5, 6},
new int[] {10, 5, 6, 9, 3, 8, 9, 1, 3},
new int[] { 0, 9, 1, 5, 6,10},
new int[] { 8, 0, 3,10, 5, 6},
new int[] {10, 5, 6},
new int[] {11, 7, 5,11, 5,10},
new int[] { 3, 0, 8, 7, 5,10, 7,10,11},
new int[] { 9, 0, 1,10,11, 7,10, 7, 5},
new int[] { 3, 1, 9, 3, 9, 8, 7,10,11, 7, 5,10},
new int[] { 2,11, 1,11, 7, 1, 1, 7, 5},
new int[] { 0, 8, 3, 2,11, 1, 1,11, 7, 1, 7, 5},
new int[] { 9, 0, 2, 9, 2, 7, 2,11, 7, 9, 7, 5},
new int[] {11, 3, 2, 8, 5, 9, 8, 7, 5},
new int[] {10, 2, 5, 2, 3, 5, 5, 3, 7},
new int[] { 5,10, 2, 8, 5, 2, 8, 7, 5, 8, 2, 0},
new int[] { 9, 0, 1,10, 2, 5, 5, 2, 3, 5, 3, 7},
new int[] { 1,10, 2, 5, 8, 7, 5, 9, 8},
new int[] { 1, 3, 7, 1, 7, 5},
new int[] { 8, 7, 0, 0, 7, 1, 7, 5, 1},
new int[] { 0, 3, 9, 9, 3, 5, 3, 7, 5},
new int[] { 9, 7, 5, 9, 8, 7},
new int[] { 4, 5, 8, 5,10, 8, 8,10,11},
new int[] { 3, 0, 4, 3, 4,10, 4, 5,10, 3,10,11},
new int[] { 0, 1, 9, 4, 5, 8, 8, 5,10, 8,10,11},
new int[] { 5, 9, 4, 1,11, 3, 1,10,11},
new int[] { 8, 4, 5, 2, 8, 5, 2,11, 8, 2, 5, 1},
new int[] { 3, 2,11, 1, 4, 5, 1, 0, 4},
new int[] { 9, 4, 5, 8, 2,11, 8, 0, 2},
new int[] {11, 3, 2, 9, 4, 5},
new int[] { 3, 8, 4, 3, 4, 2, 2, 4, 5, 2, 5,10},
new int[] {10, 2, 5, 5, 2, 4, 2, 0, 4},
new int[] { 0, 3, 8, 5, 9, 4,10, 2, 1},
new int[] { 2, 1,10, 9, 4, 5},
new int[] { 4, 5, 8, 8, 5, 3, 5, 1, 3},
new int[] { 5, 0, 4, 5, 1, 0},
new int[] { 3, 8, 0, 4, 5, 9},
new int[] { 9, 4, 5},
new int[] { 7, 4,11, 4, 9,11,11, 9,10},
new int[] { 3, 0, 8, 7, 4,11,11, 4, 9,11, 9,10},
new int[] {11, 7, 4, 1,11, 4, 1,10,11, 1, 4, 0},
new int[] { 8, 7, 4,11, 1,10,11, 3, 1},
new int[] { 2,11, 7, 2, 7, 1, 1, 7, 4, 1, 4, 9},
new int[] { 3, 2,11, 4, 8, 7, 9, 1, 0},
new int[] { 7, 4,11,11, 4, 2, 4, 0, 2},
new int[] { 2,11, 3, 7, 4, 8},
new int[] { 2, 3, 7, 2, 7, 9, 7, 4, 9, 2, 9,10},
new int[] { 4, 8, 7, 0,10, 2, 0, 9,10},
new int[] { 2, 1,10, 0, 7, 4, 0, 3, 7},
new int[] {10, 2, 1, 8, 7, 4},
new int[] { 9, 1, 4, 4, 1, 7, 1, 3, 7},
new int[] { 1, 0, 9, 8, 7, 4},
new int[] { 3, 4, 0, 3, 7, 4},
new int[] { 8, 7, 4},
new int[] { 8, 9,10, 8,10,11},
new int[] { 0, 9, 3, 3, 9,11, 9,10,11},
new int[] { 1,10, 0, 0,10, 8,10,11, 8},
new int[] {10, 3, 1,10,11, 3},
new int[] { 2,11, 1, 1,11, 9,11, 8, 9},
new int[] {11, 3, 2, 0, 9, 1},
new int[] {11, 0, 2,11, 8, 0},
new int[] {11, 3, 2},
new int[] { 3, 8, 2, 2, 8,10, 8, 9,10},
new int[] { 9, 2, 0, 9,10, 2},
new int[] { 8, 0, 3, 1,10, 2},
new int[] {10, 2, 1},
new int[] { 8, 1, 3, 8, 9, 1},
new int[] { 9, 1, 0},
new int[] { 8, 0, 3},
new int[] {}
};
}
I know the code is really messy but the problem probably is in the CreateMesh method or in the triangulation table.
Does someone know why the hole is appearing there?
I have the triangulation table from the internet.
Thanks.
I got it fixed with a new triangulation table. Thanks for your help.
Related
TypeConversion of a string to bytearray
I have a string value: Example: string msg = "array('B', [255, 216, 255, 224, 0, 16, 74, 70, 73, 70, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 255, 219, 0, 67, 0, 2, 1, 1, 1, 1, 1, 2, 1, 1, 1, 2, 2, 2, 2, 2, 4, 3, 2, 2, 2, 2, 5, 4, 4, 3, 4, 6, 5, 6, 6, 6, 5, 6, 6, 6, 7, 9, 8, 6, 7, 9, 7, 6, 6, 8, 11, 8, 9, 10, 10, 10, 10, 10, 6, 8, 11, 12, 11, 10, 12, 9, 10, 10, 10, 255, 219, 0, 67, 1, 2, 2, 2, 2, 2, 2, 5, 3, 3, 5, 10, 7, 6, 7, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10])" I want to convert this string value to type byte[]. private byte[] data; //after type conversion from string to byte array Debug.Log("data in byte array is: " + data); Output should be: data in byte array is: [255, 216, 255, 224, 0, 16, 74, 70, 73, 70, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 255, 219, 0, 67, 0, 2, 1, 1, 1, 1, 1, 2, 1, 1, 1, 2, 2, 2, 2, 2, 4, 3, 2, 2, 2, 2, 5, 4, 4, 3, 4, 6, 5, 6, 6, 6, 5, 6, 6, 6, 7, 9, 8, 6, 7, 9, 7, 6, 6, 8, 11, 8, 9, 10, 10, 10, 10, 10, 6, 8, 11, 12, 11, 10, 12, 9, 10, 10, 10, 255, 219, 0, 67, 1, 2, 2, 2, 2, 2, 2, 5, 3, 3, 5, 10, 7, 6, 7, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10] Since the actual string msg is a very large value, I want to do this with minimum execution time possible.
Looks like a fairly simple parsing problem. We could run up a full parser for the format, but that's probably well beyond your needs. Let's assume instead that your msg is always going to be in the format shown, starting with "array('B', [", ending with "])" and having 0 or more comma-separated decimal values. Since any option you choose is going to scan the string at least once, we can design code around doing exactly that. The actual content contains only 4 types of characters: digit (0-9) comma (,) space ( ) end-array (]) We can iterate through the characters starting at the first character after the start-array ([ at offset 11) and do something with each of those character types: ignore it, update the current value, yield the current value and/or exit. If all of the assumptions are correct then this is a simple process. One scan through the characters, no allocations in the parser itself. Here's a sample: IEnumerable<byte> ParseArrayMsg(string msg) { if (!msg.StartsWith("array('B', [") || !msg.EndsWith("])")) yield break; int value = 0; for (int i = msg.IndexOf('[') + 1; i < msg.Length; i++) { var c = msg[i]; if (c == ',' || c == ']') { yield return (byte)value; value = 0; if (c == ']') break; } else if (char.IsDigit(c)) value = value * 10 + (int)(c - '0'); else if (c != ' ') throw new Exception($"Invalid character '{c}' at index '{i}'."); } } The returned enumerable can then be processed however you like. Your code won't actually produce the output you want, but this will: var data = ParseArrayMsg(msg).ToArray(); Console.WriteLine($"Data in byte array is: [{string.Join(", ", data.Select(b => b.ToString()))}]"); Data in byte array is: [255, 216, 255, 224, 0, 16, 74, 70, 73, 70, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 255, 219, 0, 67, 0, 2, 1, 1, 1, 1, 1, 2, 1, 1, 1, 2, 2, 2, 2, 2, 4, 3, 2, 2, 2, 2, 5, 4, 4, 3, 4, 6, 5, 6, 6, 6, 5, 6, 6, 6, 7, 9, 8, 6, 7, 9, 7, 6, 6, 8, 11, 8, 9, 10, 10, 10, 10, 10, 6, 8, 11, 12, 11, 10, 12, 9, 10, 10, 10, 255, 219, 0, 67, 1, 2, 2, 2, 2, 2, 2, 5, 3, 3, 5, 10, 7, 6, 7, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10]
You can try like the following: string yourString= "Your String"; // Convert a C# string to a byte array byte[] bytes = Encoding.ASCII.GetBytes(yourString);
Convert list of integers (IEnumerable<int>) to list of tuples (IEnumerable<IEnumerable<int>>) of specific length
I try to solve next exercise: Input: List of integers with count >= 1; some positive integer k Output: all possible tuples of this integers with length of k; For instance Input: {1, 2}; k = 4 Output: { {1, 1, 1, 1}, {1, 1, 1, 2}, {1, 1, 2, 1}, {1, 1, 2, 2}, {1, 2, 1, 1}, {1, 2, 1, 2}, {1, 2, 2, 1}, {1, 2, 2, 2}, {2, 1, 1, 1}, {2, 1, 1, 2}, {2, 1, 2, 1}, {2, 1, 2, 2}, {2, 2, 1, 1}, {2, 2, 1, 2}, {2, 2, 2, 1}, {2, 2, 2, 2} } I tried to create an array that contains k copies of input list and than use Combinations: public static IEnumerable<IEnumerable<T>> Combinations<T>( this IEnumerable<T> elements, int k) { return k == 0 ? new[] { new T[0] } : elements.SelectMany((e, i) => elements .Skip(i + 1) .Combinations(k - 1) .Select(c => (new[] { e }).Concat(c))); } But it takes too long when k > 9. Is there an algorithm for solving this problem in a short time?
Let's get rid of recursion and have 512 items: Code: //TODO: you may want to declare it as IEnumerable<T[]> Combinations<T> public static IEnumerable<IEnumerable<T>> Combinations<T>( this IEnumerable<T> elements, int k) { if (null == elements) throw new ArgumentNullException(nameof(elements)); else if (k < 0) throw new ArgumentOutOfRangeException(nameof(k)); T[] alphabet = elements.ToArray(); // Special cases if (alphabet.Length <= 0) yield break; else if (k == 0) yield break; int[] indexes = new int[k]; do { yield return indexes .Select(i => alphabet[i]) .ToArray(); for (int i = indexes.Length - 1; i >= 0; --i) if (indexes[i] >= alphabet.Length - 1) indexes[i] = 0; else { indexes[i] += 1; break; } } while (!indexes.All(index => index == 0)); } Demo: string report = string.Join(Environment.NewLine, Combinations(new int[] { 1, 2}, 9) .Select(line => string.Join(", ", line))); Console.Write(report); Outcome: (512 records) 1, 1, 1, 1, 1, 1, 1, 1, 1 1, 1, 1, 1, 1, 1, 1, 1, 2 1, 1, 1, 1, 1, 1, 1, 2, 1 1, 1, 1, 1, 1, 1, 1, 2, 2 1, 1, 1, 1, 1, 1, 2, 1, 1 1, 1, 1, 1, 1, 1, 2, 1, 2 1, 1, 1, 1, 1, 1, 2, 2, 1 1, 1, 1, 1, 1, 1, 2, 2, 2 1, 1, 1, 1, 1, 2, 1, 1, 1 ... 2, 2, 2, 2, 2, 2, 1, 2, 1 2, 2, 2, 2, 2, 2, 1, 2, 2 2, 2, 2, 2, 2, 2, 2, 1, 1 2, 2, 2, 2, 2, 2, 2, 1, 2 2, 2, 2, 2, 2, 2, 2, 2, 1 2, 2, 2, 2, 2, 2, 2, 2, 2 Let's generate, say, all 2**20 == 1048576 items (k = 20), i.e. more than 1 million arrays of size 20 : Stopwatch sw = new Stopwatch(); sw.Start(); int count = Combinations(new int[] { 1, 2 }, 20).Count(); sw.Stop(); Console.Write($"{count.ToString()} items at {sw.ElapsedMilliseconds:f0} milliseconds"); Outcome: 1048576 items at 469 milliseconds
C# remove duplicates from List<List<int>>
I'm having trouble coming up with the most efficient algorithm to remove duplicates from List<List<int>>, for example (I know this looks like a list of int[], but just doing it that way for visual purposes: my_list[0]= {1, 2, 3}; my_list[1]= {1, 2, 3}; my_list[2]= {9, 10, 11}; my_list[3]= {1, 2, 3}; So the output would just be new_list[0]= {1, 2, 3}; new_list[1]= {9, 10, 11}; Let me know if you have any ideas. I would really appreciate it.
Build custom of EqualityComparer<List<int>>: public class CusComparer : IEqualityComparer<List<int>> { public bool Equals(List<int> x, List<int> y) { return x.SequenceEqual(y); } public int GetHashCode(List<int> obj) { int hashCode = 0; for (var index = 0; index < obj.Count; index++) { hashCode ^= new {Index = index, Item = obj[index]}.GetHashCode(); } return hashCode; } } Then you can get the result by using Distinct with custom comparer method: var result = my_list.Distinct(new CusComparer()); Edit: Include the index into method GetHashCode to make sure different orders will not be equal
This simple program does what you want: using System; using System.Collections.Generic; using System.Linq; namespace ConsoleApplication6 { class Program { static void Main(string[] args) { List<List<int>> lists = new List<List<int>>(); lists.Add(new List<int> { 1, 2, 3 }); lists.Add(new List<int> { 1, 2, 3 }); lists.Add(new List<int> { 9, 10, 11 }); lists.Add(new List<int> { 1, 2, 3 }); var distinct = lists.Select(x => new HashSet<int>(x)) .Distinct(HashSet<int>.CreateSetComparer()); foreach (var list in distinct) { foreach (var v in list) { Console.Write(v + " "); } Console.WriteLine(); } } } }
var finalList = lists.GroupBy(x => String.Join(",", x)) .Select(x => x.First().ToList()) .ToList();
You can use the LINQ Distinct overload that takes a comparer. The comparer should see if the lists are equal. Note that the default equals operations of lists won't do what you're really looking for, so the comparer will need to loop through each for you. Here's an example of such a comparer: public class SequenceComparer<T> : IEqualityComparer<IEnumerable<T>> { IEqualityComparer<T> itemComparer; public SequenceComparer() { this.itemComparer = EqualityComparer<T>.Default; } public SequenceComparer(IEqualityComparer<T> itemComparer) { this.itemComparer = itemComparer; } public bool Equals(IEnumerable<T> x, IEnumerable<T> y) { if (object.Equals(x, y)) return true; if (x == null || y == null) return false; return x.SequenceEqual(y, itemComparer); } public int GetHashCode(IEnumerable<T> obj) { if (obj == null) return -1; int i = 0; return obj.Aggregate(0, (x, y) => x ^ new { Index = i++, ItemHash = itemComparer.GetHashCode(y) }.GetHashCode()); } } Update: I got the idea of using an anonymous type to make a better hash from Cuong Le's answer, and I LINQ-ified it and made it work in my class.
For small sets of data, a comparer could be useful, but if you have 1000 or more List> then trying to compare them all could begin to take a long amount of time. I suggest that you instead use your data to build a distinct tree. The building of the tree will be much faster and when you are done you can always bring your data back into your old data structure.
I wanted to compare the performance of the answers of #Leniel Macaferi and #L.B as I wasn't sure which would be more performant, or if the difference would be significant. It turns out that the difference is very significant: Method 1: 00:00:00.0976649 #Leniel Macaferi Method 2: 00:00:32.0961650 #L.B Here is the code I used to benchmark them: public static void Main(string[] args) { var list = new List<List<int>> {new List<int> {1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3,}, new List<int> {1, 2, 31, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 6}, new List<int> {1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 9, 10, 11, 1}, new List<int> {1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 9}, new List<int> {1, 2, 31, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 6, 7}, new List<int> {1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 9, 10, 11}, new List<int> {1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3,}, new List<int> {1, 2, 31, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 6}, new List<int> {1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 9, 10, 11}}; var sw1 = new Stopwatch(); sw1.Start(); for (var i = 0; i < 1_000_000; i++) { var distinct = list.Select(x => new HashSet<int>(x)).Distinct(HashSet<int>.CreateSetComparer()); } sw1.Stop(); Console.WriteLine($"Method 1: {sw1.Elapsed}"); var sw2 = new Stopwatch(); sw2.Start(); for (var i = 0; i < 1_000_000; i++) { var distinct = list.GroupBy(a => string.Join(",", a)).Select(a => a.First()).ToList(); } sw2.Stop(); Console.WriteLine($"Method 2: {sw2.Elapsed}"); Console.ReadKey(); }
error Method name expected
private void button1_Click(object sender, EventArgs e) { int[] ml = new int[10] ( 1, 2, 3, 4, 5, 6, 7, 8, 9 ); MessageBox.Show(Convert.ToString(ml.Length), "Length"); } I get this error can someone tell me what I am doing wrong Error 1 Method name expected C:\Users\Admin\AppData\Local\Temporary Projects\WindowsFormsApplication1\Form1.cs 21 24 WindowsFormsApplication1
int[] ml = new int[10] ( 1, 2, 3, 4, 5, 6, 7, 8, 9 ); Should be int[] ml = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
In C# array values are surrounded by { and } and not parens. Switch to using them in the array declaration and the error will go away. int[] ml = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
What's wrong with my multidimensional - array declaration? C#
private int[, ,] table = new int[4 , 5 , 5]{ {{0,6,2,6,4},{2,2,4,2,8},{4,4,8,4,6},{6,6,2,6,4},{8,8,6,8,2}}, {{0,2,8,8,4},{2,4,6,6,8},{4,8,2,2,6},{6,2,8,8,4},{8,6,4,4,2}}, {{0,4,2,4,4},{2,8,4,8,8},{4,6,8,6,6},{6,4,2,4,4},{8,2,6,2,2}}, {{0,8,8,2,4},{2,6,6,4,8},{4,2,2,8,6},{6,8,8,2,4},{8,4,4,6,2}} }; I want this table: k|l 0 1 2 3 4 0 06264 22428 44846 66264 88682 1 02884 24668 48226 62884 86442 2 04244 28488 46866 64244 82622 3 08824 26648 42286 68824 84462 thanks for help
There's nothing wrong with your declaration. It compiles fine and I can write something like this: for (int i = 0; i < 4; i++) { for (int j = 0; j < 5; j++) { for (int k = 0; k < 5; k++) { var x = table[i, j, k]; } } } Update: sure you can shorten it a tiny bit. Since the array dimensions are given by your initial values, you can write it like this: private int[,,] table = new [,,]{ <your numbers go here> };
you need a 2 dimensional array, its [4,5] array
Try skipping the new int[4 , 5 , 5] part, the compiler should be able to find out the dimensions. Otherwise I don't see any problem.
Nothing is wrong. It works flawlessly for me. What problem exactly you have?
The compiler can figure out the length of each dimension for you, so let it do all the hard work: private int[,,] table = new int[,,]{ {{0,6,2,6,4},{2,2,4,2,8},{4,4,8,4,6},{6,6,2,6,4},{8,8,6,8,2}}, {{0,2,8,8,4},{2,4,6,6,8},{4,8,2,2,6},{6,2,8,8,4},{8,6,4,4,2}}, {{0,4,2,4,4},{2,8,4,8,8},{4,6,8,6,6},{6,4,2,4,4},{8,2,6,2,2}}, {{0,8,8,2,4},{2,6,6,4,8},{4,2,2,8,6},{6,8,8,2,4},{8,4,4,6,2}} }; And this gives you the output you want, apart from the header: StringBuilder stringBuilder = new StringBuilder(); for (int row = 0; row < table.GetLength(0); ++row) { stringBuilder.Append(row.ToString() + "\t"); for (int column = 0; column < table.GetLength(1); ++column) { for (int valueIndex = 0; valueIndex < table.GetLength(2); ++valueIndex) { stringBuilder.Append(table[row, column, valueIndex].ToString()); } stringBuilder.Append("\t"); } stringBuilder.AppendLine(); } string result = stringBuilder.ToString(); Console.WriteLine(result);
Just change new int[4 , 5 , 5] with new[,,] this is what you should have : var table = new[,,] { {{0, 6, 2, 6, 4}, {2, 2, 4, 2, 8}, {4, 4, 8, 4, 6}, {6, 6, 2, 6, 4}, {8, 8, 6, 8, 2}}, {{0, 2, 8, 8, 4}, {2, 4, 6, 6, 8}, {4, 8, 2, 2, 6}, {6, 2, 8, 8, 4}, {8, 6, 4, 4, 2}}, {{0, 4, 2, 4, 4}, {2, 8, 4, 8, 8}, {4, 6, 8, 6, 6}, {6, 4, 2, 4, 4}, {8, 2, 6, 2, 2}}, {{0, 8, 8, 2, 4}, {2, 6, 6, 4, 8}, {4, 2, 2, 8, 6}, {6, 8, 8, 2, 4}, {8, 4, 4, 6, 2}} };
That piece of code won't compile if you have it in the wrong place - if you have it inside a function then drop the private modifier. (If it is declared at class level then it is fine).