import io.data2viz.color.*
import io.data2viz.geom.*
import io.data2viz.math.*
import io.data2viz.viz.*
import kotlin.math.*
private fun GroupNode.drawText(text:String, pos:Point, color:Color) {
text {
textContent = text
textColor = Colors.Web.white
x = pos.x
y = pos.y
vAlign = TextVAlign.MIDDLE
hAlign = TextHAlign.MIDDLE
fontWeight = FontWeight.BOLD
fontSize = 20.0
}
text {
textContent = text
textColor = color
x = pos.x
y = pos.y
vAlign = TextVAlign.MIDDLE
hAlign = TextHAlign.MIDDLE
fontSize = 20.0
}
}
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 rectangle top-left corner
var rectX = -60.0
var rectY = 40.0
// The rectangle size
var rectWidth = 220.0
var rectHeight = 160.0
// The current rotation angle
var rotation = 0.rad
viz {
size = appSize
val centerLayer = layer()
val rectLayer = layer()
val boundsLayer = layer()
// mark the center of rotation
centerLayer.apply {
circle {
fill = Colors.Web.black
x = offset.x
y = offset.y
radius = 3.0
}
drawText("O", offset + Point(10.0, 10.0), Colors.Web.black)
}
animation {
// Increment the rotation
rotation += 0.02.rad
// Draw the rotated rectangle (using a transformation)
rectLayer.apply {
clear()
group {
transform {
translate(offset.x, offset.y)
rotate(rotation.rad)
}
rect {
strokeColor = Colors.Web.blue
fill = Colors.Web.blue.withAlpha(20.pct)
x = rectX
y = rectY
width = rectWidth
height = rectHeight
}
}
}
// Draw the bounding box and the rotated corners of the rectangle
boundsLayer.apply {
clear()
group {
transform {
translate(offset.x, offset.y)
}
val rxcos = rectX * rotation.cos
val rxsin = rectX * rotation.sin
val rwcos = rectWidth * rotation.cos
val rwsin = rectWidth * rotation.sin
val rysin = rectY * rotation.sin
val rycos = rectY * rotation.cos
val rhcos = rectHeight * rotation.cos
val rhsin = rectHeight * 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)
// get min/max coordinates to draw the bounding box
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)))
rect {
x = minX
y = minY
width = maxX - minX
height = maxY - minY
strokeColor = Colors.Web.red
}
drawText("A", a, Colors.Web.blue)
drawText("B", b, Colors.Web.blue)
drawText("C", c, Colors.Web.blue)
drawText("D", d, Colors.Web.blue)
drawText("E", Point(minX, minY), Colors.Web.red)
drawText("F", Point(maxX, minY), Colors.Web.red)
drawText("G", Point(maxX, maxY), Colors.Web.red)
drawText("H", Point(minX, maxY), Colors.Web.red)
}
}
}
}.bindRendererOnNewCanvas()
}