/// <summary> /// Returns the center square of the given sqaure's partition. /// </summary> /// <param name="sq"></param> /// <returns></returns> private MazeSquare ReferenceSquare(MazeSquare sq) { // x and y index of the current square's partition int px = sq.XPos * xPartitions / xSize, py = sq.YPos * yPartitions / ySize; // x and y coordinates of the selected partition's center square int xCenter = (2 * px + 1) * xSize / (2 * xPartitions); int yCenter = (2 * py + 1) * ySize / (2 * yPartitions); // Apply this partition's offset. if (xOffCenter != null && yOffCenter != null) { xCenter += xOffCenter[px, py]; yCenter += yOffCenter[px, py]; } // If defined: Find the vertex closest to the given square. if (vertices != null) { MazeSquare closestVertex = vertices[0]; double closestDistance = Maze.Distance(sq, closestVertex); for (int i = 1; i < vertices.Length; i++) { double d = Maze.Distance(sq, vertices[i]); if (d < closestDistance) { closestVertex = vertices[i]; closestDistance = d; } } xCenter = closestVertex.XPos; yCenter = closestVertex.YPos; } return(new MazeSquare(xCenter, yCenter)); }
public override bool[] PreferredDirections(MazeSquare sq) { bool[] result = new bool[4] { false, false, false, false }; #region Collect the distances of all neighbor squares (including diagonals) from the reference square. // Actually, this is the (absolute) difference between the distances of a neighbor square and sq itself. double[,] distances = new double[3, 3]; // The distance of the current square to the reference square should be approximated. MazeSquare sq0 = this.ReferenceSquare(sq); double d0 = Maze.Distance(sq, sq0); // Rounding to the next integer will approximate circles in 1 unit steps. if (approximateCircles) { d0 = Math.Round(d0); } for (int i = -1; i <= +1; i++) { for (int j = -1; j <= +1; j++) { // Note: this[x,y] is not defined outside the maze size. MazeSquare sq1 = new MazeSquare(sq.XPos + i, sq.YPos + j); distances[i + 1, j + 1] = (minimizeDistance ? +1 : -1) * Math.Abs(Maze.Distance(sq1, sq0) - d0); } } #endregion #region Find a range of distances including the current square and two of the neighbors. double d1 = double.MaxValue, d2 = double.MaxValue; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { if (i == 1 && j == 1) // Discard the current square. { continue; } if (distances[i, j] >= d2) // Discard distances greater than the current second best. { continue; } if (distances[i, j] >= d1) // This is a new second best distance. { d2 = distances[i, j]; } else // This is a new best distance. { d2 = d1; d1 = distances[i, j]; } } } #endregion #region Add the directions to the two best neighbors to the result. if (distances[1, 0] <= d2) // straight north { result[(int)WallPosition.WP_N] = true; } if (distances[0, 1] <= d2) // straight west { result[(int)WallPosition.WP_W] = true; } if (distances[1, 2] <= d2) // straight south { result[(int)WallPosition.WP_S] = true; } if (distances[2, 1] <= d2) // straight east { result[(int)WallPosition.WP_E] = true; } // For approximating a diagonal connection, we follow the closer path (unless this logic is inverted). if (distances[0, 0] <= d2) // north-west { result[(int)((distances[1, 0] < distances[0, 1] == followDiagonals) ? WallPosition.WP_N : WallPosition.WP_W)] = true; } if (distances[2, 0] <= d2) // north-east { result[(int)((distances[1, 0] < distances[2, 1] == followDiagonals) ? WallPosition.WP_N : WallPosition.WP_E)] = true; } if (distances[0, 2] <= d2) // south-west { result[(int)((distances[1, 2] < distances[0, 1] == followDiagonals) ? WallPosition.WP_S : WallPosition.WP_W)] = true; } if (distances[2, 2] <= d2) // south-east { result[(int)((distances[1, 2] < distances[2, 1] == followDiagonals) ? WallPosition.WP_S : WallPosition.WP_E)] = true; } #endregion return(result); }