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 remove Color 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.