@@ -3,26 +3,37 @@ package org.openrndr.extra.shapes.primitives
33import org.openrndr.draw.Drawer
44import org.openrndr.math.Vector2
55import org.openrndr.shape.Rectangle
6- import org.openrndr.shape.contour
76import org.openrndr.shape.ShapeContour
7+ import org.openrndr.shape.contour
88import kotlin.jvm.JvmRecord
99import kotlin.math.min
1010
11+ /* *
12+ * Rounded rectangle. When `radii` are given (instead of `radius`), they are specified clockwise
13+ * starting at the top-left. Fewer than 4 values are accepted and repeated cyclically.
14+ * (e.g., providing 2 values alternates them, providing 1 value applies it to all corners).
15+ */
1116@JvmRecord
12- data class RoundedRectangle (val corner : Vector2 , val width : Double , val height : Double , val radius : Double ) {
13- constructor (x: Double , y: Double , width: Double , height: Double , radius: Double ) : this (
14- Vector2 (x, y),
15- width,
16- height,
17- radius
18- )
19-
20- constructor (rectangle: Rectangle , radius: Double ) : this (
21- rectangle.corner,
22- rectangle.width,
23- rectangle.height,
24- radius
25- )
17+ data class RoundedRectangle (val corner : Vector2 , val width : Double , val height : Double , val radii : List <Double >) {
18+
19+ init {
20+ require(radii.isNotEmpty()) { " RoundedRectangle can't be constructed with zero radii" }
21+ }
22+
23+ constructor (x: Double , y: Double , width: Double , height: Double , radii: List <Double >) :
24+ this (Vector2 (x, y), width, height, radii)
25+
26+ constructor (rectangle: Rectangle , radii: List <Double >) :
27+ this (rectangle.corner, rectangle.width, rectangle.height, radii)
28+
29+ constructor (corner: Vector2 , width: Double , height: Double , radius: Double ) :
30+ this (corner, width, height, listOf (radius))
31+
32+ constructor (x: Double , y: Double , width: Double , height: Double , radius: Double ) :
33+ this (Vector2 (x, y), width, height, listOf (radius))
34+
35+ constructor (rectangle: Rectangle , radius: Double ) :
36+ this (rectangle.corner, rectangle.width, rectangle.height, listOf (radius))
2637
2738 /* * the center of the rounded rectangle */
2839 val center: Vector2
@@ -35,35 +46,46 @@ data class RoundedRectangle(val corner: Vector2, val width: Double, val height:
3546 val contour
3647 get() = contour {
3748 // A higher radius than half the width/height makes it go weird
38- val r = min(min(radius, width / 2 ), height / 2 )
49+ val r = List (4 ) {
50+ min(min(radii[it % radii.size], width / 2 ), height / 2 )
51+ }
3952
40- moveTo(x + r, y)
41- lineTo(x + width - r, y)
53+ moveTo(x + r[ 0 ] , y)
54+ lineTo(x + width - r[ 1 ] , y)
4255
43- arcTo(r, r, 90.0 , false , true , Vector2 (x + width, y + r))
44- lineTo(x + width, y + height - r)
56+ arcTo(r[ 1 ] , r[ 1 ] , 90.0 , false , true , Vector2 (x + width, y + r[ 1 ] ))
57+ lineTo(x + width, y + height - r[ 2 ] )
4558
46- arcTo(r, r, 90.0 , false , true , Vector2 (x + width - r, y + height))
47- lineTo(x + r, y + height)
59+ arcTo(r[ 2 ] , r[ 2 ] , 90.0 , false , true , Vector2 (x + width - r[ 2 ] , y + height))
60+ lineTo(x + r[ 3 ] , y + height)
4861
49- arcTo(r, r, 90.0 , false , true , Vector2 (x, y + height - r))
50- lineTo(x, y + r)
62+ arcTo(r[ 3 ] , r[ 3 ] , 90.0 , false , true , Vector2 (x, y + height - r[ 3 ] ))
63+ lineTo(x, y + r[ 0 ] )
5164
52- arcTo(r, r, 90.0 , false , true , Vector2 (x + r, y))
53- close()
54- }
65+ arcTo(r[0 ], r[0 ], 90.0 , false , true , Vector2 (x + r[0 ], y))
66+ close() }
5567
5668 val shape
5769 get() = contour.shape
5870}
5971
72+ fun Drawer.roundedRectangle (roundedRectangle : RoundedRectangle ) =
73+ contour(roundedRectangle.contour)
74+
75+ // radii
76+ fun Drawer.roundedRectangle (x : Double , y : Double , width : Double , height : Double , radii : List <Double >) =
77+ contour(RoundedRectangle (x, y, width, height, radii).contour)
78+
79+ fun Drawer.roundedRectangle (position : Vector2 , width : Double , height : Double , radii : List <Double >) =
80+ contour(RoundedRectangle (position, width, height, radii).contour)
81+
82+ fun Rectangle.toRounded (radii : List <Double >) = RoundedRectangle (this , radii)
83+
84+ // radius
6085fun Drawer.roundedRectangle (x : Double , y : Double , width : Double , height : Double , radius : Double ) =
61- contour(RoundedRectangle (x, y, width, height, radius).contour)
86+ contour(RoundedRectangle (x, y, width, height, listOf ( radius) ).contour)
6287
6388fun Drawer.roundedRectangle (position : Vector2 , width : Double , height : Double , radius : Double ) =
64- contour(RoundedRectangle (position, width, height, radius).contour)
65-
66- fun Drawer.roundedRectangle (roundedRectangle : RoundedRectangle ) =
67- contour(roundedRectangle.contour)
89+ contour(RoundedRectangle (position, width, height, listOf (radius)).contour)
6890
69- fun Rectangle.toRounded (radius : Double ) = RoundedRectangle (this , radius)
91+ fun Rectangle.toRounded (radius : Double ) = RoundedRectangle (this , listOf ( radius) )
0 commit comments