package net.trivernis.chunkmaster.lib.shapes import kotlin.math.PI import kotlin.math.abs import kotlin.math.pow import kotlin.math.sqrt class Spiral(center: Pair, start: Pair, radius: Int): Shape(center, start, radius) { private var direction = 0 override fun endReached(): Boolean { val distances = getDistances(center, currentPos) return radius > 0 && (distances.first > radius || distances.second > radius) } override fun progress(): Double { return (count / (radius * 2).toDouble().pow(2)).coerceAtMost(100.0) } override fun currentRadius(): Int { val distances = getDistances(center, currentPos) return distances.first.coerceAtLeast(distances.second) } /** * Returns the next value in the spiral */ override fun next(): Pair { if (count == 0 && currentPos != center) { // simulate the spiral to get the correct direction and count val simSpiral = Spiral(center, center, radius) while (simSpiral.next() != currentPos); direction = simSpiral.direction count = simSpiral.count } if (count == 1) { // because of the center behaviour count ++ return currentPos } if (currentPos == center) { // the center has to be handled exclusively currentPos = Pair(center.first, center.second + 1) count ++ return center } else { val distances = getDistances(center, currentPos) if (abs(distances.first) == abs(distances.second)) { direction = (direction + 1)%5 } } when(direction) { 0 -> { currentPos = Pair(currentPos.first + 1, currentPos.second) } 1 -> { currentPos = Pair(currentPos.first, currentPos.second - 1) } 2 -> { currentPos = Pair(currentPos.first - 1, currentPos.second) } 3 -> { currentPos = Pair(currentPos.first, currentPos.second + 1) } 4 -> { currentPos = Pair(currentPos.first, currentPos.second + 1) direction = 0 } } count ++ return currentPos } /** * Returns the edges to be used with dynmap markers */ override fun getShapeEdgeLocations(): List> { val a = Pair(this.radius + center.first, this.radius + center.second) val b = Pair(this.radius + center.first, -this.radius + center.second) val c = Pair(-this.radius + center.first, -this.radius + center.second) val d = Pair(-this.radius + center.first, this.radius + center.second) return listOf(a, b, c, d, a) } /** * Returns the distances between 2 coordinates */ private fun getDistances(pos1: Pair, pos2: Pair): Pair { return Pair(pos2.first - pos1.first, pos2.second - pos1.second) } }