Make Point and Size honest to goodness structs
This commit is contained in:
parent
5607f01ac1
commit
6b6e317a9c
2 changed files with 61 additions and 57 deletions
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue