Migrating a ray tracer from Java and Groovy to Kotlin (part 1)
February 25, 2018
After reading the wonderful book Kotlin in Action I started to migrate my ray tracer from Java and Groovy to Kotlin.
The ray tracer consisted mainly of code written in Java 7 with a Groovy DSL and some utility classes on top of it.
- Java: ray tracer, mathematics, geometry
- Groovy: DSL, GUI, utilities
- Swing GUI, command line UI
As a first step I converted the Java classes to Kotlin using the Java-to-Kotlin transformation built into IntelliJ IDEA. This was not always possible without errors, especially for generic classes.
Some not related changes not related especially related to Kotlin.
- always use
Double
for floating point arithmetic - Only provide one type of
Color
and removeColor
as a parameter - Implement
Matrix
as a single array, not as an array of arrays - Use JUnit5, remove spock
I am especially fond of the operator overloading. The following class for two dimensional vectors overrides addition and multiplication operators and adds some infix
dot products.
class Vector2D(x: Double, y: Double) : Element2D(x, y) {
operator fun plus(v: Vector2D) = Vector2D(x + v.x, y + v.y)
operator fun minus(v: Vector2D) = Vector2D(x - v.x, y - v.y)
operator fun times(s: Double) = Vector2D(s * x, s * y)
infix fun dot(v: Vector2D): Double = x * v.x + y * v.y
infix fun dot(v: Normal): Double = x * v.x + y * v.y
operator fun unaryMinus() = Vector2D(-x, -y)
fun normalize(): Vector2D {
val l = length()
return Vector2D(x / l, y / l)
}
}
operator fun Double.times(v: Vector2D) = Vector2D(this * v.x, this * v.y)
This can be used as following:
val v = Vector2D(1.0, 2.0)
val w = Vector2D(3.0, -1.0)
val x = Vector2D(-1.0, 1.0)
val result = -v dot (2.0 * (w + x))
assertEquals(-4.0, result)
Mathematical code can be expressed much simpler with Kotlin.