Figuring out `arcTo()`

arcTo

I was having some difficulties understanding the contour { ... arcTo } method, so I wrote this helper program which uses a GUI to change the arc parameters:

import org.openrndr.application
import org.openrndr.color.ColorRGBa
import org.openrndr.extra.gui.GUI
import org.openrndr.extra.parameters.BooleanParameter
import org.openrndr.extra.parameters.Description
import org.openrndr.extra.parameters.DoubleParameter
import org.openrndr.shape.contour

fun main() = application {
    configure { }
    program {
        val gui = GUI()
        val conf = @Description("Arc") object {
            @DoubleParameter("crx", 0.0, 640.0, order = 5)
            var crx = 0.0

            @DoubleParameter("cry", 0.0, 480.0, order = 10)
            var cry = 0.0

            @DoubleParameter("angle", -180.0, 180.0, order = 15)
            var angle = 0.0

            @BooleanParameter("largeArcFlag", order = 20)
            var largeArcFlag = true

            @BooleanParameter("sweepFlag", order = 25)
            var sweepFlag = true

            @DoubleParameter("tx", 0.0, 640.0, order = 30)
            var tx = 0.0

            @DoubleParameter("ty", 0.0, 480.0, order = 35)
            var ty = 0.0
        }
        extend(gui) {
            compartmentsCollapsedByDefault = false
            add(conf)
        }
        extend {
            drawer.clear(ColorRGBa.WHITE)
            drawer.contour(
                contour {
                    moveTo(drawer.bounds.center)
                    arcTo(conf.crx, conf.cry, conf.angle, conf.largeArcFlag, conf.sweepFlag, conf.tx, conf.ty)
                }
            )
        }
    }
}

The arcTo method is based on this code.

I realized that in my case I always want crx to be equal to cry. In that case angle seems to have no effect.

I’ll share a function to draw an arc with a center, a start point and an end point soon.

1 Like

arcFromCenter

/**
 * Create a [ShapeContour] arc specifying the [center],
 * [start] point and [end] point.
 *
 * The distance from [center] to both [start] and [end] must be equal,
 * otherwise an empty contour is returned.
 */
fun arcFromCenter(center: Vector2, start: Vector2, end: Vector2) =
    if (center.squaredDistanceTo(start) != center.squaredDistanceTo(end))
        ShapeContour.EMPTY
    else
        contour {
            val d = center.distanceTo(start)
            val side = ((start.x - center.x) * (end.y - center.y) -
                    (start.y - center.y) * (end.x - center.x)) > 0

            moveTo(start)
            arcTo(d, d, 0.0, !side, true, end)
        }

Usage

apps.simpleTests.ArcFromCenter-2022-12-28-13.05.06

import org.openrndr.application
import org.openrndr.color.ColorRGBa
import org.openrndr.color.ColorXSVa
import org.openrndr.shape.Rectangle

fun main() = application {
    program {
        val center = drawer.bounds.center
        val rect = Rectangle.fromCenter(center, 200.0).contour
        val arcs = rect.segments.map {
            // create an arc for each segment of a square
            arcFromCenter(it.position(0.5), it.start, it.end).close()
        }
        extend {
            drawer.clear(ColorRGBa.WHITE)
            drawer.fill = null
            drawer.contour(rect)
            arcs.forEachIndexed { i, arc ->
                drawer.fill = ColorXSVa(i * 90.0, 0.5, 1.0).toRGBa()
                drawer.contour(arc)
            }
        }
    }
}