Infinity Symbol

Let’s have some fun by drawing a dynamic infinity symbol using Jetpack Compose. We’ll also add a simple animation to bring it to life.

First, let’s understand the mathematical representation of the infinity symbol. There is a simple equation that can help us shape it accurately.

Infinity Symbol Equation

\( x(\theta) = \frac{scale \cdot \cos(\theta)}{1 + \sin^2(\theta)} \)

Infinity Symbol Equation

\( y(\theta) = \frac{\text{scale} \cdot \sin(\theta) \cdot \cos(\theta)}{1 + \sin^2(\theta)} \)

Infinity Symbol Equation

\( \theta =[0, 2\pi] \)

At this point, the range is often used in parametric equations because it represents a full cycle around the unit circle. This static range for theta() provides a comprehensive set of values, ensuring we have enough points to accurately draw the complete shape of the infinity symbol.

data class InfinityCoordinate(val x: Float, val y: Float)
Kotlin
fun calculateCoordinates(theta: Double, scale: Float) = InfinityCoordinate(
    (scale * cos(theta) / (1 + sin(theta) * sin(theta))).toFloat(),
    (scale * sin(theta) * cos(theta) / (1 + sin(theta) * sin(theta))).toFloat()
)
Kotlin

Now, we have a function representing the mathematical equation, let’s create a helper function to generate values based on a given range.

fun generateSequenceInRange(start: Double, end: Double, step: Double) =
    generateSequence(start) { it + step }.takeWhile { it <= end }.toList()
Kotlin

With these functions in place, we can begin drawing using a custom path.

@Composable
fun DrawInfinity(
    .
    .
    thetaValues: List<Double>
) {
    Canvas {

        val path = Path().apply {

            var firstPoint = true

            for (theta in thetaValues) {

                val (x, y) = calculateCoordinates(theta = theta, scale = 300f)

               // Translate coordinates to the middle of the canvas
                val xMiddleOfCanvas = x + size.width / 2
                val yMiddleOfCanvas = y + size.height / 2

               // Move to the starting point or draw a line segment
                if (firstPoint) {
                    moveTo(xMiddleOfCanvas, yMiddleOfCanvas)
                    firstPoint = false
                } else {
                    lineTo(xMiddleOfCanvas, yMiddleOfCanvas)
                }

            }
        }

        drawPath(
            path = path,
            brush = brush,
            style = Stroke(width = stroke)
        )
    }
}
Kotlin

Let’s call the DrawInfinity function and provide it with the theta values.

setContent {
    Box {
        DrawInfinity(
            thetaValues = generateSequenceInRange(0.0, 2 * PI, 0.001)
        )
    }
}
Kotlin

Thanks for reading! If you want to see animation code please check out the code here.


Leave a Reply

Your email address will not be published. Required fields are marked *