import io.data2viz.color.*
import io.data2viz.geom.*
import io.data2viz.math.*
import io.data2viz.viz.*
import kotlin.math.*
// compute a boundingBox from a rotating rectangle
private fun Rect.rotate(rotation:Angle): Rect {
val rxcos = x * rotation.cos
val rxsin = x * rotation.sin
val rwcos = width * rotation.cos
val rwsin = width * rotation.sin
val rysin = y * rotation.sin
val rycos = y * rotation.cos
val rhcos = height * rotation.cos
val rhsin = height * rotation.sin
// compute point ABCD of the rotated rectangle
val a = Point(rxcos - rysin, rxsin + rycos)
val b = Point(a.x + rwcos, a.y + rwsin)
val c = Point(b.x - rhsin, b.y + rhcos)
val d = Point(a.x - rhsin, a.y + rhcos)
val minX = min(a.x, min(b.x, min(c.x, d.x)))
val minY = min(a.y, min(b.y, min(c.y, d.y)))
val maxX = max(a.x, max(b.x, max(c.x, d.x)))
val maxY = max(a.y, max(b.y, max(c.y, d.y)))
return RectGeom(minX, minY, maxX - minX, maxY - minY)
}
private fun GroupNode.recursiveRectangle(previous: Rect, rotation: Angle) =
drawRectAndBoundingBox(previous.rotate(rotation), rotation)
private fun GroupNode.drawRectAndBoundingBox(rect: Rect, rotation: Angle): Rect {
group {
transform {
rotate(rotation.rad)
}
rect {
x = rect.x
y = rect.y
width = rect.width
height = rect.height
fill = Colors.hsl(rotation, 100.pct, 50.pct).withAlpha(2.pct)
strokeColor = Colors.hsl(rotation*2, 100.pct, 20.pct).withAlpha(80.pct)
}
}
val boundingBox = rect.rotate(rotation)
rect {
x = boundingBox.x
y = boundingBox.y
width = boundingBox.width
height = boundingBox.height
fill = Colors.hsl(rotation, 80.pct, 50.pct).withAlpha(2.pct)
strokeColor = Colors.hsl(rotation*.2, 100.pct, 20.pct).withAlpha(80.pct)
}
return boundingBox
}
fun main() {
val appSize = size(600, 600)
// Offset is used to translate things at the center of the screen
val offset = Point(appSize.width / 2.0, appSize.height / 2.0)
// The base rectangle
val rect = RectGeom(-1.0, -1.0, 2.0, 2.0)
// The current rotation angle
var rotation = 0.rad
viz {
size = appSize
val boundsLayer = layer()
animation {
// Increment the rotation
rotation += 0.01.rad
// Draw the bounding box and the rotated corners of the rectangle
boundsLayer.apply {
clear()
group {
transform {
translate(offset.x, offset.y)
rotate(rotation.rad)
}
var r = rect as Rect
(0 .. 30).forEach { index ->
r = recursiveRectangle(r, rotation * (1 + (index / 100.0)))
}
}
}
}
}.bindRendererOnNewCanvas()
}