avatarElye

Summary

This article discusses how to use the Jetpack Compose Canvas API to draw quadratic and cubic Bezier curves in Android development.

Abstract

The article begins by introducing the concept of drawing arcs in Jetpack Compose Canvas Path Drawing and explains why it is only useful for perfect circular curves. It then introduces the concept of Bezier curves and how they can be used to draw more complex curves that are not fixed to a perfect circular curve. The article explains the math behind quadratic and cubic Bezier curves and provides code examples for using the Jetpack Compose Canvas API to draw them. The article also includes animations to help illustrate how the curves are drawn.

Opinions

  • The author believes that learning about Bezier curves is important for Android developers who want to create more complex and aesthetically pleasing graphics in their applications.
  • The author suggests that understanding the math behind Bezier curves can be helpful in understanding how they work.
  • The author provides code examples and animations to help illustrate the concepts discussed in the article, suggesting that visual aids can be helpful in understanding complex topics.
  • The author also suggests that Bezier curves can be used to create more complex graphics, such as plotting a graph, and provides examples of how to do so.

Learning Android

Learn Jetpack Compose Canvas Cubic and Quadratic Bezier And Its Usage

Thoroughly Understand Cubic and Quadratic Bezier and Its Usage in Jetpack Compose

Photo by Ryan Stone on Unsplash

I just shared about drawing arcs in Jetpack Compose Canvas Path Drawing. However, it is only useful for something that is having a perfect circular curve (like a circle or oval).

What if we want to have something that can have a slight curve or more, and is not fixed to a perfect circular curve, like plotting a graph

Or even drawing a well-connected curvy line given relatively scattered points as shown below

If you are wondering why can’t we just use lines to achieve this, look at the below, aesthetically, lines are not good for these.

So, here I’m going to illustrate how Bezier Curvy lines API works, for both the Jetpack Compose Canvas Path provided.

fun quadraticBezierTo(x1: Float, y1: Float, x2: Float, y2: Float)
fun cubicTo(x1: Float, y1: Float, x2: Float, y2: Float, x3: Float, y3: Float)

The maths of it

Just some basic understanding… helps us know math class in school is useful sometimes. 😛

Quadratic Bezier

This is actually plotting a graph of ax² + bx + c = 0.

From school, if we remember this is a polynomial graph of something like below. You’ll notice there’s a curve of any 2 given linear points.

Cubic Bezier

This is actually plotting a graph of ax³ + ax² + bx + c = 0.

This is plotting a graph as below. Differing from Quadratic Bezier, it can have 2 curves instead of one.

Plotting the Curve

To make learning more interesting, instead of explaining it, let me illustrate it using some animation as shown below.

Quadratic Bezier

Firstly, we notice the function has 2 points, x1, y1, and x2, y2.

fun quadraticBezierTo(x1: Float, y1: Float, x2: Float, y2: Float)

To plot the Quadratic line, 3 points are required. The first point (Point1) though is from its previous path (lineTo, lineTo, etc), hence leaving 2 points (Point2 and Point3) to set.

So if I set the other 2 points through a linear interpolation (using the Lerp function. An excellent tutorial on Lerp can be found here.) change, whereby we

  • Interpolate Point1 to Point2; newPoint1 = lerp(point1, point2, t)
  • Interpolate Point2 to Point3; newPoint2 = lerp(point2, point3, t)
  • Plot the points with the same interpolated scale in the drawn line above; plotPoint = lern (newPoint1, newPoint2, t)

With this in place, now we can plot the curve as shown below. From here you clearly see how your Point1, Point2 and Point3 will determine how the curve is drawn.

Cubic Bezier

We notice the function has 3 points, x1, y1, x2, y2, and x3, y3.

fun cubicTo(x1: Float, y1: Float, x2: Float, y2: Float, x3: Float, y3: Float)

To plot the Quadratic line, 4 points are required. The first point (Point1) though is from its previous path (lineTo, lineTo, etc), hence leaving 3points (Point2, Point3, and Point4) to set.

So if I set the other 3 points through a linear interpolation (using the Lerp function. An excellent tutorial on Lerp can be found here.) change, whereby we

  • Interpolate Point1 to Point2; newPoint1 = lerp(point1, point2, t)
  • Interpolate Point2 to Point3; newPoint2 = lerp(point2, point3, t)
  • Interpolate Point3 to Point4; newPoint3 = lerp(point3, point4, t)
  • At the same time, interpolate from newPoint1 and newPoint2; interpolatePoint1 = lerp(newPoint1, newPoint2, t)
  • Also, interpolate from newPoint2 and newPoint3 simultaneously; interpolatePoint2 = lerp(newPoint1, newPoint2, t)
  • Plot the points with the same interpolated scale in the drawn line above; plotPoint = lern (interpolatePoint1, interpolatePoint2, t)

With this in place, now we can plot the curve as shown below. From here you clearly see how your Point1, Point2, Point3, and Point3 will determine how the curve is drawn.

To make the plotting more interesting, let’s change the targetted starting point differently.

Application of Bezier

Just to. make learning fun, I’ll show a simple application of each Bezier below

Quadratic Bezier: Smoothen points drawing

Assume I have 4 points below, using a line drawing, it will look really stiff.

However, if I plot using, where I use the average of previous and current points as the destination point (Point3), while the previous point is the supporting anchor for the curve (Point 2), given the Point1 is already fixed by the previous drawn point, it will curve the drawing.

path.quadraticBezierTo(
    previousX, previousY,
    (previousX + currentX)/2, (previousX + currentY)/x
)

Except for the last point, as I wanted to hit the final given red dot, so my last point will just use existing given points, instead of using an average.

path.quadraticBezierTo(
    previousX, previousY,
    currentX, currentY
)

While this looks like the plot line is quite a distance from the original dots (Red dots), if we have more plot points, it looks more decent as below.

It can also be used to plot a graph, as shown below

However, it has one clear disadvantage, that is in the event when the graph is up and down continuously, the plotted graph can get really disconnected from the actual point, as shown below.

This is where Cubic Bezier will come in handy.

Cubic Bezier: Double curving the graph plotting

The problem with Quadratic Bezier is, it has only one curve.

In the event between 2 points, it needs two curves due to the up-down graph trend, the Quadratic Bezier will fail here.

But Cubic Bezier comes in handy, as it can have 2 curves between each point.

It can plot the previous graph much better as seen here.

The formula drawn here is quite simple, whereby in between the 2 points, add the Cubic Bezier supporting points where

  • Point2 = MiddleX, PreviousY
  • Point3 = MiddleX, CurrentY
  • Point4 = CrrentX, CurrentY
    path.cubicTo(
        (previousX + currentX) / 2, previousY,
        (previousX + currentX) / 2, currentY,
        currentX, currentY
    )

This formula is applied to all points of the graph (except for the first point of the path which is a MoveTo function).

Issues with graph plotting.

While this looks perfect, there is an issue with this generic formula.

If we have not just an up-down graph, but also some relatively linear plot of a graph, the entire plot will look like below

You’ll notice the graph looks decent at the start but looks wrong subsequently

If we plot it with Quadratic Bezier, it looks like below

It is disconnected at the start.

How can we fix this? Can we have something better?

Yes, there’s more learning from me on how to plot a better graph, where the result is below. It is shared in this article below

P/S: For all the above, you can get the design here.. Enjoy playing with it.

Android App Development
Programming
App Development
Mobile App Development
Jetpack Compose
Recommended from ReadMedium
avatarNine Pages Of My Life
Flow Layouts in Jetpack Compose

🎯Index

4 min read