[orx-shapes] Add gradient to BezierPatch

This commit is contained in:
Edwin Jakobs
2020-10-12 22:31:25 +02:00
parent f980989ff6
commit 14434ec93b
2 changed files with 92 additions and 7 deletions

View File

@@ -0,0 +1,42 @@
import org.openrndr.application
import org.openrndr.color.ColorRGBa
import org.openrndr.extensions.Screenshots
import org.openrndr.extensions.SingleScreenshot
import org.openrndr.extra.shapes.bezierPatch
import org.openrndr.shape.Circle
fun main() {
application {
configure {
width = 800
height = 800
}
program {
if (System.getProperty("takeScreenshot") == "true") {
extend(SingleScreenshot()) {
this.outputFile = System.getProperty("screenshotPath")
}
}
extend {
drawer.clear(ColorRGBa.PINK)
val bp = bezierPatch(Circle(width / 2.0, height / 2.0, 350.0).contour)
for (i in 0..50) {
drawer.stroke = ColorRGBa.BLACK.opacify(1.0)
}
for (j in 1 until 50 step 2) {
for (i in 1 until 50 step 2) {
val p = bp.position(i / 50.0, j / 50.0)
val g2 = bp.gradient(i / 50.0, j / 50.0).normalized
val g = g2.perpendicular()
drawer.lineSegment(p, p + g2 * 10.0)
drawer.lineSegment(p, p - g2 * 10.0)
drawer.lineSegment(p, p + g * 10.0)
drawer.lineSegment(p, p - g * 10.0)
}
}
}
}
}
}

View File

@@ -1,5 +1,6 @@
package org.openrndr.extra.shapes
import org.openrndr.math.Matrix44
import org.openrndr.math.Vector2
import org.openrndr.shape.Rectangle
import org.openrndr.shape.Segment
@@ -24,7 +25,18 @@ class BezierPatch(val points: List<List<Vector2>>) {
)
)
private fun coeffs(t: Double): DoubleArray {
fun transform(transform: Matrix44) = BezierPatch(points.map { r ->
r.map { (transform * it.xy01).div.xy }
})
private fun coeffs2(t: Double): DoubleArray {
val it = 1.0 - t
val it2 = it * it
val t2 = t * t
return doubleArrayOf(it2, 2 * it * t, t2)
}
private fun coeffs3(t: Double): DoubleArray {
val it = 1.0 - t
val it2 = it * it
val it3 = it2 * it
@@ -39,8 +51,8 @@ class BezierPatch(val points: List<List<Vector2>>) {
* @param v a value between 0 and 1
*/
fun position(u: Double, v: Double): Vector2 {
val csu = coeffs(u)
val csv = coeffs(v)
val csu = coeffs3(u)
val csv = coeffs3(v)
var result = Vector2.ZERO
for (j in 0 until 4) {
for (i in 0 until 4) {
@@ -50,6 +62,37 @@ class BezierPatch(val points: List<List<Vector2>>) {
return result
}
/**
* Return a gradient vector on the patch by using its u,v parameterization
* @param u a value between 0 and 1
* @param v a value between 0 and 1
*/
fun gradient(u: Double, v: Double): Vector2 {
val f0 = List(4) { MutableList(3) { Vector2.ZERO } }
for (j in 0 until 4) {
for (i in 0 until 3) {
f0[j][i] = points[j][i+1] - points[j][i]
}
}
val f1 = List(3) { MutableList(3) { Vector2.ZERO } }
for (j in 0 until 3) {
for (i in 0 until 3) {
f1[j][i] = f0[j+1][i] - f0[j][i]
}
}
val csu = coeffs2(u)
val csv = coeffs2(v)
var result = Vector2.ZERO
for (j in 0 until 3) {
for (i in 0 until 3) {
result += f1[j][i] * csu[i] * csv[j]
}
}
return result
}
/**
* Generate a random point on the path
* @return a point that is uniformly distributed in uv space
@@ -57,7 +100,7 @@ class BezierPatch(val points: List<List<Vector2>>) {
fun randomPoint(random: Random = Random.Default) = position(random.nextDouble(), random.nextDouble())
fun horizontal(v: Double): ShapeContour {
val cs = coeffs(v)
val cs = coeffs3(v)
val cps = Array(4) { Vector2.ZERO }
for (j in 0 until 4) {
for (i in 0 until 4) {
@@ -68,7 +111,7 @@ class BezierPatch(val points: List<List<Vector2>>) {
}
fun vertical(u: Double): ShapeContour {
val cs = coeffs(u)
val cs = coeffs3(u)
val cps = Array(4) { Vector2.ZERO }
for (j in 0 until 4) {
for (i in 0 until 4) {