diff --git a/Terrain2/Algorithms.swift b/Terrain2/Algorithms.swift index 0506dc5..526446b 100644 --- a/Terrain2/Algorithms.swift +++ b/Terrain2/Algorithms.swift @@ -182,7 +182,7 @@ public class DiamondSquareAlgorithm: Algorithm { } var subdivisions: [Box] { - guard size.w > 1 && size.h > 1 else { + guard size.w > 2 && size.h > 2 else { return [] } let midp = midpoint @@ -194,6 +194,15 @@ public class DiamondSquareAlgorithm: Algorithm { Box(origin: (origin.x + newSize.w, origin.y + newSize.h), size: newSize) ] } + + func breadthFirstSearch(visit: (Box) -> (Void)) { + var queue = [self] + while queue.count > 0 { + let box = queue.removeFirst() + visit(box) + queue.append(contentsOf: box.subdivisions) + } + } } let name = "Diamond-Square" @@ -236,7 +245,7 @@ public class DiamondSquareAlgorithm: Algorithm { } } - breadthFirstSearch(ofGridWithSize: size) { (box: Box) in + box.breadthFirstSearch { (box: Box) in let halfSize = (w: box.size.w / 2 + 1, h: box.size.h / 2 + 1) // 1. Diamond. Average the corners, add a random value. Set the midpoint. @@ -281,15 +290,6 @@ public class DiamondSquareAlgorithm: Algorithm { texture.replace(region: region, mipmapLevel: 0, withBytes: heightMap, bytesPerRow: MemoryLayout.stride * size.width) } - private func breadthFirstSearch(ofGridWithSize size: MTLSize, visit: (Box) -> (Void)) { - var queue = [Box(origin: (0, 0), size: (size.width, size.height))] - while queue.count > 0 { - let box = queue.removeFirst() - visit(box) - queue.append(contentsOf: box.subdivisions) - } - } - // MARK: Algorithm var outTexture: MTLTexture { diff --git a/Terrain2Tests/AlgorithmsTests.swift b/Terrain2Tests/AlgorithmsTests.swift index ed9d212..17858b1 100644 --- a/Terrain2Tests/AlgorithmsTests.swift +++ b/Terrain2Tests/AlgorithmsTests.swift @@ -14,7 +14,43 @@ public typealias Point = DiamondSquareAlgorithm.Box.Point public typealias Size = DiamondSquareAlgorithm.Box.Size class DiamondSquareBFSTests: XCTestCase { + func testBFS() { + let box = Box(origin: (x: 3, y: 4), size: (w: 5, h: 5)) + var expectedBoxes: [Box] = [ + box, + Box(origin: (x: 3, y: 4), size: (w: 3, h: 3)), + Box(origin: (x: 6, y: 4), size: (w: 3, h: 3)), + Box(origin: (x: 3, y: 7), size: (w: 3, h: 3)), + Box(origin: (x: 6, y: 7), size: (w: 3, h: 3)), + Box(origin: (x: 3, y: 4), size: (w: 2, h: 2)), + Box(origin: (x: 5, y: 4), size: (w: 2, h: 2)), + Box(origin: (x: 3, y: 6), size: (w: 2, h: 2)), + Box(origin: (x: 5, y: 6), size: (w: 2, h: 2)), + + Box(origin: (x: 6, y: 4), size: (w: 2, h: 2)), + Box(origin: (x: 8, y: 4), size: (w: 2, h: 2)), + Box(origin: (x: 6, y: 6), size: (w: 2, h: 2)), + Box(origin: (x: 8, y: 6), size: (w: 2, h: 2)), + + Box(origin: (x: 3, y: 7), size: (w: 2, h: 2)), + Box(origin: (x: 5, y: 7), size: (w: 2, h: 2)), + Box(origin: (x: 3, y: 9), size: (w: 2, h: 2)), + Box(origin: (x: 5, y: 9), size: (w: 2, h: 2)), + + Box(origin: (x: 6, y: 7), size: (w: 2, h: 2)), + Box(origin: (x: 8, y: 7), size: (w: 2, h: 2)), + Box(origin: (x: 6, y: 9), size: (w: 2, h: 2)), + Box(origin: (x: 8, y: 9), size: (w: 2, h: 2)), + ].reversed() + + box.breadthFirstSearch { (box: Box) -> (Void) in + let exBox = expectedBoxes.popLast() + XCTAssertNotNil(exBox) + XCTAssertEqual(box, exBox!) + } + XCTAssertEqual(expectedBoxes.count, 0) + } } class DiamondSquareBoxTests: XCTestCase {