/// <summary> /// Calculates a vector in world coordinates whose transformation by the <paramref name="projection"/> results /// in the vector (0, -1). /// </summary> /// <param name="projection">The projection to consider.</param> /// <returns>The vector in world coordinates that gets transformed to the vector (0, -1).</returns> public static PointD CalculateHeightVector(Matrix2D projection) { var proj = projection.Clone(); proj.Invert(); return(proj.Transform(new PointD(0d, -1d))); }
static (int, int) SimulateWithAdjecency(Matrix2D <char> matrix, Func <int, int, Matrix2D <char>, int[]> adjacencyFunc = null, int crowdedThreshold = 4, bool output = false) { if (adjacencyFunc == null) { adjacencyFunc = FindImmediateNeighbours; } int[] indices = new int[128 * 128]; //max 128*128 int[][] adjacencyLists = new int[128 * 128][]; //max 128*128 for (int y = 0; y < matrix.Height; y++) { for (int x = 0; x < matrix.Width; x++) { int index = (y << 7) + x; var ptr = matrix.GetIndex(x, y); indices[index] = ptr; adjacencyLists[index] = adjacencyFunc(x, y, matrix); } } var current = matrix; var next = matrix.Clone(); int numFlipped = 1; int iterations = 0; while (numFlipped > 0) { numFlipped = 0; for (int y = 0; y < matrix.Height; y++) { for (int x = 0; x < matrix.Width; x++) { int index = (y << 7) + x; var adjacency = adjacencyLists[index]; if (adjacency == null) { continue; //null or floor } var ptr = indices[index]; var c = current.Array[ptr]; if (c == 'L' && IsClear(adjacency, current)) { next.Array[ptr] = '#'; numFlipped++; } else if (c == '#' && IsCrowded(adjacency, current, crowdedThreshold)) { next.Array[ptr] = 'L'; numFlipped++; } else { next.Array[ptr] = current.Array[ptr]; } } } if (output) { Console.CursorLeft = 0; Console.CursorTop = 0; next.Dump(); Thread.Sleep(50); } //bufferswap var tmp = current; current = next; next = tmp; iterations++; } return(current.Array.Count(c => c == '#'), iterations); }