Make Point and Size honest to goodness structs

This commit is contained in:
Eryn Wells 2018-11-10 13:50:28 -05:00
parent 5607f01ac1
commit 6b6e317a9c
2 changed files with 61 additions and 57 deletions

View file

@ -125,18 +125,20 @@ class RandomAlgorithm: Kernel, TerrainGenerator {
/// Implementation of the Diamond-Squares algorithm. /// Implementation of the Diamond-Squares algorithm.
/// - https://en.wikipedia.org/wiki/Diamond-square_algorithm /// - https://en.wikipedia.org/wiki/Diamond-square_algorithm
public class DiamondSquareAlgorithm: TerrainGenerator { public class DiamondSquareAlgorithm: TerrainGenerator {
public struct Box { public struct Point {
public typealias Point = (x: Int, y: Int) let x: Int
public typealias Size = (w: Int, h: Int) let y: Int
}
public struct Size {
let w: Int
let h: Int
}
public struct Box {
let origin: Point let origin: Point
let size: Size let size: Size
init(origin o: Point, size s: Size) {
origin = o
size = s
}
var corners: [Point] { var corners: [Point] {
return [northwest, southwest, northeast, northwest] return [northwest, southwest, northeast, northwest]
} }
@ -146,19 +148,19 @@ public class DiamondSquareAlgorithm: TerrainGenerator {
} }
var north: Point { var north: Point {
return (x: origin.x + (size.w / 2 + 1), y: origin.y) return Point(x: origin.x + (size.w / 2 + 1), y: origin.y)
} }
var west: Point { var west: Point {
return (x: origin.x, y: origin.y + (size.h / 2 + 1)) return Point(x: origin.x, y: origin.y + (size.h / 2 + 1))
} }
var south: Point { var south: Point {
return (x: origin.x + (size.w / 2 + 1), y: origin.y + size.h) return Point(x: origin.x + (size.w / 2 + 1), y: origin.y + size.h)
} }
var east: Point { var east: Point {
return (x: origin.x + size.w, y: origin.y + (size.h / 2 + 1)) return Point(x: origin.x + size.w, y: origin.y + (size.h / 2 + 1))
} }
var northwest: Point { var northwest: Point {
@ -166,19 +168,19 @@ public class DiamondSquareAlgorithm: TerrainGenerator {
} }
var southwest: Point { var southwest: Point {
return (x: origin.x, y: origin.y + size.h) return Point(x: origin.x, y: origin.y + size.h)
} }
var northeast: Point { var northeast: Point {
return (x: origin.x + size.w, y: origin.y) return Point(x: origin.x + size.w, y: origin.y)
} }
var southeast: Point { var southeast: Point {
return (x: origin.x + size.w, y: origin.y + size.h) return Point(x: origin.x + size.w, y: origin.y + size.h)
} }
var midpoint: Point { var midpoint: Point {
return (x: origin.x + (size.w / 2 + 1), y: origin.y + (size.h / 2 + 1)) return Point(x: origin.x + (size.w / 2 + 1), y: origin.y + (size.h / 2 + 1))
} }
var subdivisions: [Box] { var subdivisions: [Box] {
@ -186,12 +188,12 @@ public class DiamondSquareAlgorithm: TerrainGenerator {
return [] return []
} }
let midp = midpoint let midp = midpoint
let newSize = (w: midp.x - origin.x, h: midp.y - origin.y) let newSize = Size(w: midp.x - origin.x, h: midp.y - origin.y)
return [ return [
Box(origin: origin, size: newSize), Box(origin: origin, size: newSize),
Box(origin: (origin.x + newSize.w, origin.y), size: newSize), Box(origin: Point(x: origin.x + newSize.w, y: origin.y), size: newSize),
Box(origin: (origin.x, origin.y + newSize.h), size: newSize), Box(origin: Point(x: origin.x, y: origin.y + newSize.h), size: newSize),
Box(origin: (origin.x + newSize.w, origin.y + newSize.h), size: newSize) Box(origin: Point(x: origin.x + newSize.w, y: origin.y + newSize.h), size: newSize)
] ]
} }
@ -230,14 +232,14 @@ public class DiamondSquareAlgorithm: TerrainGenerator {
func render() { func render() {
let size = DiamondSquareAlgorithm.textureSize let size = DiamondSquareAlgorithm.textureSize
func ptToIndex(_ pt: Box.Point) -> Int { func ptToIndex(_ pt: Point) -> Int {
return pt.y * size.width + pt.x return pt.y * size.width + pt.x
} }
var heightMap = [Float](repeating: 0, count: size.width * size.height) var heightMap = [Float](repeating: 0, count: size.width * size.height)
// 0. Set the corners to initial values if they haven't been set yet. // 0. Set the corners to initial values if they haven't been set yet.
let box = Box(origin: (0, 0), size: (size.width, size.height)) let box = Box(origin: Point(x: 0, y: 0), size: Size(w: size.width, h: size.height))
for p in box.corners { for p in box.corners {
let idx = ptToIndex(p) let idx = ptToIndex(p)
if heightMap[idx] == 0.0 { if heightMap[idx] == 0.0 {
@ -303,6 +305,18 @@ public class DiamondSquareAlgorithm: TerrainGenerator {
} }
} }
extension DiamondSquareAlgorithm.Point: Equatable {
public static func == (lhs: DiamondSquareAlgorithm.Point, rhs: DiamondSquareAlgorithm.Point) -> Bool {
return lhs.x == rhs.x && lhs.y == rhs.y
}
}
extension DiamondSquareAlgorithm.Size: Equatable {
public static func == (lhs: DiamondSquareAlgorithm.Size, rhs: DiamondSquareAlgorithm.Size) -> Bool {
return lhs.w == rhs.w && lhs.h == rhs.h
}
}
extension DiamondSquareAlgorithm.Box: Equatable { extension DiamondSquareAlgorithm.Box: Equatable {
public static func == (lhs: DiamondSquareAlgorithm.Box, rhs: DiamondSquareAlgorithm.Box) -> Bool { public static func == (lhs: DiamondSquareAlgorithm.Box, rhs: DiamondSquareAlgorithm.Box) -> Bool {
return lhs.origin == rhs.origin && lhs.size == rhs.size return lhs.origin == rhs.origin && lhs.size == rhs.size

View file

@ -14,52 +14,50 @@ public typealias Point = DiamondSquareAlgorithm.Box.Point
public typealias Size = DiamondSquareAlgorithm.Box.Size public typealias Size = DiamondSquareAlgorithm.Box.Size
class DiamondSquareBoxTests: XCTestCase { class DiamondSquareBoxTests: XCTestCase {
fileprivate let box = Box(origin: Point(x: 3, y: 4), size: Size(w: 5, h: 5))
func testMidpoint() { func testMidpoint() {
let box = Box(origin: (x: 3, y: 4), size: (w: 5, h: 5))
let midpoint = box.midpoint let midpoint = box.midpoint
XCTAssertEqual(midpoint.x, 6) XCTAssertEqual(midpoint.x, 6)
XCTAssertEqual(midpoint.y, 7) XCTAssertEqual(midpoint.y, 7)
} }
func testSubdivision() { func testSubdivision() {
let box = Box(origin: (x: 3, y: 4), size: (w: 5, h: 5))
let subdivs = box.subdivisions let subdivs = box.subdivisions
XCTAssertEqual(subdivs.count, 4) XCTAssertEqual(subdivs.count, 4)
XCTAssertEqual(subdivs[0], Box(origin: (x: 3, y: 4), size: (w: 3, h: 3))) XCTAssertEqual(subdivs[0], Box(origin: Point(x: 3, y: 4), size: Size(w: 3, h: 3)))
XCTAssertEqual(subdivs[1], Box(origin: (x: 6, y: 4), size: (w: 3, h: 3))) XCTAssertEqual(subdivs[1], Box(origin: Point(x: 6, y: 4), size: Size(w: 3, h: 3)))
XCTAssertEqual(subdivs[2], Box(origin: (x: 3, y: 7), size: (w: 3, h: 3))) XCTAssertEqual(subdivs[2], Box(origin: Point(x: 3, y: 7), size: Size(w: 3, h: 3)))
XCTAssertEqual(subdivs[3], Box(origin: (x: 6, y: 7), size: (w: 3, h: 3))) XCTAssertEqual(subdivs[3], Box(origin: Point(x: 6, y: 7), size: Size(w: 3, h: 3)))
} }
func testBFS() { func testBFS() {
let box = Box(origin: (x: 3, y: 4), size: (w: 5, h: 5))
var expectedBoxes: [Box] = [ var expectedBoxes: [Box] = [
box, box,
Box(origin: (x: 3, y: 4), size: (w: 3, h: 3)), Box(origin: Point(x: 3, y: 4), size: Size(w: 3, h: 3)),
Box(origin: (x: 6, y: 4), size: (w: 3, h: 3)), Box(origin: Point(x: 6, y: 4), size: Size(w: 3, h: 3)),
Box(origin: (x: 3, y: 7), size: (w: 3, h: 3)), Box(origin: Point(x: 3, y: 7), size: Size(w: 3, h: 3)),
Box(origin: (x: 6, y: 7), size: (w: 3, h: 3)), Box(origin: Point(x: 6, y: 7), size: Size(w: 3, h: 3)),
Box(origin: (x: 3, y: 4), size: (w: 2, h: 2)), Box(origin: Point(x: 3, y: 4), size: Size(w: 2, h: 2)),
Box(origin: (x: 5, y: 4), size: (w: 2, h: 2)), Box(origin: Point(x: 5, y: 4), size: Size(w: 2, h: 2)),
Box(origin: (x: 3, y: 6), size: (w: 2, h: 2)), Box(origin: Point(x: 3, y: 6), size: Size(w: 2, h: 2)),
Box(origin: (x: 5, y: 6), size: (w: 2, h: 2)), Box(origin: Point(x: 5, y: 6), size: Size(w: 2, h: 2)),
Box(origin: (x: 6, y: 4), size: (w: 2, h: 2)), Box(origin: Point(x: 6, y: 4), size: Size(w: 2, h: 2)),
Box(origin: (x: 8, y: 4), size: (w: 2, h: 2)), Box(origin: Point(x: 8, y: 4), size: Size(w: 2, h: 2)),
Box(origin: (x: 6, y: 6), size: (w: 2, h: 2)), Box(origin: Point(x: 6, y: 6), size: Size(w: 2, h: 2)),
Box(origin: (x: 8, y: 6), size: (w: 2, h: 2)), Box(origin: Point(x: 8, y: 6), size: Size(w: 2, h: 2)),
Box(origin: (x: 3, y: 7), size: (w: 2, h: 2)), Box(origin: Point(x: 3, y: 7), size: Size(w: 2, h: 2)),
Box(origin: (x: 5, y: 7), size: (w: 2, h: 2)), Box(origin: Point(x: 5, y: 7), size: Size(w: 2, h: 2)),
Box(origin: (x: 3, y: 9), size: (w: 2, h: 2)), Box(origin: Point(x: 3, y: 9), size: Size(w: 2, h: 2)),
Box(origin: (x: 5, y: 9), size: (w: 2, h: 2)), Box(origin: Point(x: 5, y: 9), size: Size(w: 2, h: 2)),
Box(origin: (x: 6, y: 7), size: (w: 2, h: 2)), Box(origin: Point(x: 6, y: 7), size: Size(w: 2, h: 2)),
Box(origin: (x: 8, y: 7), size: (w: 2, h: 2)), Box(origin: Point(x: 8, y: 7), size: Size(w: 2, h: 2)),
Box(origin: (x: 6, y: 9), size: (w: 2, h: 2)), Box(origin: Point(x: 6, y: 9), size: Size(w: 2, h: 2)),
Box(origin: (x: 8, y: 9), size: (w: 2, h: 2)), Box(origin: Point(x: 8, y: 9), size: Size(w: 2, h: 2)),
].reversed() ].reversed()
box.breadthFirstSearch { (box: Box) -> (Void) in box.breadthFirstSearch { (box: Box) -> (Void) in
@ -73,28 +71,24 @@ class DiamondSquareBoxTests: XCTestCase {
// MARK: Sides // MARK: Sides
func testNorth() { func testNorth() {
let box = Box(origin: (x: 3, y: 4), size: (w: 5, h: 5))
let pt = box.north let pt = box.north
XCTAssertEqual(pt.x, 6) XCTAssertEqual(pt.x, 6)
XCTAssertEqual(pt.y, 4) XCTAssertEqual(pt.y, 4)
} }
func testWest() { func testWest() {
let box = Box(origin: (x: 3, y: 4), size: (w: 5, h: 5))
let pt = box.west let pt = box.west
XCTAssertEqual(pt.x, 3) XCTAssertEqual(pt.x, 3)
XCTAssertEqual(pt.y, 7) XCTAssertEqual(pt.y, 7)
} }
func testSouth() { func testSouth() {
let box = Box(origin: (x: 3, y: 4), size: (w: 5, h: 5))
let pt = box.south let pt = box.south
XCTAssertEqual(pt.x, 6) XCTAssertEqual(pt.x, 6)
XCTAssertEqual(pt.y, 9) XCTAssertEqual(pt.y, 9)
} }
func testEast() { func testEast() {
let box = Box(origin: (x: 3, y: 4), size: (w: 5, h: 5))
let pt = box.east let pt = box.east
XCTAssertEqual(pt.x, 8) XCTAssertEqual(pt.x, 8)
XCTAssertEqual(pt.y, 7) XCTAssertEqual(pt.y, 7)
@ -103,28 +97,24 @@ class DiamondSquareBoxTests: XCTestCase {
// MARK: Corners // MARK: Corners
func testNorthwest() { func testNorthwest() {
let box = Box(origin: (x: 3, y: 4), size: (w: 5, h: 5))
let pt = box.northwest let pt = box.northwest
XCTAssertEqual(pt.x, 3) XCTAssertEqual(pt.x, 3)
XCTAssertEqual(pt.y, 4) XCTAssertEqual(pt.y, 4)
} }
func testNortheast() { func testNortheast() {
let box = Box(origin: (x: 3, y: 4), size: (w: 5, h: 5))
let pt = box.northeast let pt = box.northeast
XCTAssertEqual(pt.x, 8) XCTAssertEqual(pt.x, 8)
XCTAssertEqual(pt.y, 4) XCTAssertEqual(pt.y, 4)
} }
func testSouthwest() { func testSouthwest() {
let box = Box(origin: (x: 3, y: 4), size: (w: 5, h: 5))
let pt = box.southwest let pt = box.southwest
XCTAssertEqual(pt.x, 3) XCTAssertEqual(pt.x, 3)
XCTAssertEqual(pt.y, 9) XCTAssertEqual(pt.y, 9)
} }
func testSoutheast() { func testSoutheast() {
let box = Box(origin: (x: 3, y: 4), size: (w: 5, h: 5))
let pt = box.southeast let pt = box.southeast
XCTAssertEqual(pt.x, 8) XCTAssertEqual(pt.x, 8)
XCTAssertEqual(pt.y, 9) XCTAssertEqual(pt.y, 9)