Fixes to orx-color and orx-shapes (#296)

This commit is contained in:
Abe Pazos
2023-03-21 09:57:26 +01:00
committed by GitHub
parent 8e3e4bddb0
commit 7412ae4595
5 changed files with 109 additions and 17 deletions

View File

@@ -1,12 +1,14 @@
import org.openrndr.application
import org.openrndr.color.ColorRGBa
import org.openrndr.draw.loadFont
import org.openrndr.extensions.SingleScreenshot
import org.openrndr.extra.color.spaces.*
import org.openrndr.extra.color.palettes.rangeTo
fun main() {
application {
configure {
height = 30 + 50 * 11 // row count
}
program {
extend {
drawer.clear(ColorRGBa.WHITE)

View File

@@ -7,27 +7,61 @@ import org.openrndr.shape.Circle
import org.openrndr.shape.LineSegment
import org.openrndr.shape.ShapeContour
class Net(val point0: Vector2, val point1: Vector2, val circle: Circle) : LinearType<Net> {
override fun div(scale: Double) = Net(point0 / scale, point1 / scale, circle / scale)
class Net(val point0: Vector2, val point1: Vector2, val circle: Circle) :
LinearType<Net> {
override fun div(scale: Double) =
Net(point0 / scale, point1 / scale, circle / scale)
override fun times(scale: Double) = Net(point0 * scale, point1 * scale, circle * scale)
override fun times(scale: Double) =
Net(point0 * scale, point1 * scale, circle * scale)
override fun plus(right: Net) = Net(point0 + right.point0, point1 + right.point1, circle + right.circle)
override fun plus(right: Net) =
Net(point0 + right.point0, point1 + right.point1, circle + right.circle)
override fun minus(right: Net) = Net(point0 - right.point0, point1 - right.point1, circle - right.circle)
override fun minus(right: Net) =
Net(point0 - right.point0, point1 - right.point1, circle - right.circle)
/**
* Creates a [ShapeContour] with three segments: two [LineSegment] and one [Arc].
* These three components form a contour that resemble a string starting
* at [point0], wrapping around the [circle] and ending at [point1].
* If one of the points is inside the circle only a line segment tangent
* to the circle that starts at the other point is returned. If both
* points are inside the circle an empty contour is returned.
*/
val contour: ShapeContour
get() {
val tangents0 = circle.tangents(point0)
val tangents1 = circle.tangents(point1)
var k = LineSegment(point0, tangents0.first).contour
run {
val th0 = Polar.fromVector(tangents0.first - circle.center).theta
var th1 = Polar.fromVector(tangents1.second - circle.center).theta
if (th1 < th0) th1 += 360.0
k += Arc(circle.center, circle.radius, th0, th1).contour
val p0Inside = circle.contains(point0)
val p1Inside = circle.contains(point1)
return when {
!p0Inside && !p1Inside -> {
val tangents0 = circle.tangents(point0)
val tangents1 = circle.tangents(point1)
val th0 =
Polar.fromVector(tangents0.first - circle.center).theta
val th1 =
Polar.fromVector(tangents1.second - circle.center).theta
LineSegment(point0, tangents0.first).contour +
Arc(
circle.center,
circle.radius,
th0,
if (th1 < th0) th1 + 360.0 else th1
).contour +
LineSegment(tangents1.second, point1).contour
}
p0Inside ->
LineSegment(circle.tangents(point1).second, point1).contour
p1Inside ->
LineSegment(circle.tangents(point0).first, point0).contour
else ->
ShapeContour.EMPTY
}
k += LineSegment(tangents1.second, point1).contour
return k
}
}

View File

@@ -8,6 +8,10 @@ import kotlin.math.PI
import kotlin.math.cos
import kotlin.math.sin
/**
* Creates a regular polygon at [center] with the given [sides] and [radius].
* Specify a [phase] in degrees to rotate it.
*/
fun regularPolygon(sides: Int, center: Vector2 = Vector2.ZERO, radius: Double = 100.0, phase: Double = 0.0): ShapeContour {
val c = contour {
val phi = phase.asRadians
@@ -22,6 +26,11 @@ fun regularPolygon(sides: Int, center: Vector2 = Vector2.ZERO, radius: Double =
return c
}
/**
* Creates a rounded polygon at [center] with the given [sides] and [radius].
* Specify a [phase] in degrees to rotate it.
* [roundFactor] 0.0 = no rounding, 0.5 = default, 1.0 = full rounding.
*/
fun regularPolygonRounded(sides: Int, roundFactor: Double = 0.5, center: Vector2 = Vector2.ZERO, radius: Double = 100.0, phase: Double = 0.0): ShapeContour {
val c = contour {
val phi = phase.asRadians
@@ -60,6 +69,13 @@ fun regularPolygonRounded(sides: Int, roundFactor: Double = 0.5, center: Vector2
return c
}
/**
* Creates a beveled polygon at [center] with the given [sides] and [radius].
* Specify a [phase] in degrees to rotate it.
* If 0.0 < [bevelFactor] < 1.0 the number of [sides] is doubled.
* Using 0.5 all sides have equal length. With other values [bevelFactor]
* determines the length ratio between even and odd sides.
*/
fun regularPolygonBeveled(sides: Int, bevelFactor: Double = 0.5, center: Vector2 = Vector2.ZERO, radius: Double = 100.0, phase: Double = 0.0): ShapeContour {
val c = contour {
val phi = phase.asRadians

View File

@@ -2,11 +2,14 @@ package org.openrndr.extra.shapes
import org.openrndr.draw.Drawer
import org.openrndr.math.Vector2
import org.openrndr.shape.Rectangle
import org.openrndr.shape.contour
import org.openrndr.shape.ShapeContour
import kotlin.math.min
class RoundedRectangle(val corner: Vector2, val width: Double, val height: Double, val radius: Double) {
constructor(x: Double, y: Double, width: Double, height: Double, radius: Double) : this(Vector2(x, y), width, height, radius)
constructor(rectangle: Rectangle, radius: Double) : this(rectangle.corner, rectangle.width, rectangle.height, radius)
/** the center of the rounded rectangle */
val center: Vector2
@@ -36,6 +39,9 @@ class RoundedRectangle(val corner: Vector2, val width: Double, val height: Doubl
curveTo(Vector2(x, y), Vector2(x + r, y))
close()
}
val shape
get() = contour.shape
}
fun Drawer.roundedRectangle(x: Double, y: Double, width: Double, height: Double, radius: Double) =
@@ -45,4 +51,6 @@ fun Drawer.roundedRectangle(position: Vector2, width: Double, height: Double, ra
contour(RoundedRectangle(position, width, height, radius).contour)
fun Drawer.roundedRectangle(roundedRectangle: RoundedRectangle) =
contour(roundedRectangle.contour)
contour(roundedRectangle.contour)
fun Rectangle.toRounded(radius: Double) = RoundedRectangle(this, radius)

View File

@@ -0,0 +1,32 @@
import org.openrndr.application
import org.openrndr.color.ColorRGBa
import org.openrndr.extra.shapes.Net
import org.openrndr.shape.Circle
import kotlin.math.sin
fun main() {
application {
program {
extend {
drawer.clear(ColorRGBa.BLACK)
drawer.stroke = ColorRGBa.WHITE
drawer.fill = ColorRGBa.PINK
val a = drawer.bounds.position(0.7, 0.5)
val b = drawer.bounds.position(0.3, 0.5)
val c = Circle(
drawer.bounds.position(
sin(seconds) * 0.35 + 0.5,
sin(seconds * 2) * 0.25 + 0.5
), 50.0
)
val net = Net(a, b, c)
drawer.circle(a, 10.0)
drawer.circle(b, 10.0)
drawer.circle(c)
drawer.strokeWeight = 2.0
drawer.contour(net.contour)
}
}
}
}