[orx-shapes] Add gradient to BezierPatch
This commit is contained in:
42
orx-shapes/src/demo/kotlin/DemoBezierPatch04.kt
Normal file
42
orx-shapes/src/demo/kotlin/DemoBezierPatch04.kt
Normal 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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) {
|
||||
@@ -139,7 +182,7 @@ fun bezierPatch(shapeContour: ShapeContour, alpha: Double = 1.0 / 3.0): BezierPa
|
||||
listOf(c3.control[1], x00, x01, c1.control[0]),
|
||||
listOf(c3.control[0], x10, x11, c1.control[1]),
|
||||
listOf(c2.end, c2.control[1], c2.control[0], c2.start),
|
||||
)
|
||||
)
|
||||
return BezierPatch(cps)
|
||||
}
|
||||
|
||||
@@ -157,7 +200,7 @@ fun bezierPatch(corners: List<Vector2>, alpha: Double = 1.0 / 3.0): BezierPatch
|
||||
|
||||
/**
|
||||
* Distort a shape contour
|
||||
*/
|
||||
*/
|
||||
fun BezierPatch.distort(shapeContour: ShapeContour, referenceRectangle: Rectangle = shapeContour.bounds): ShapeContour {
|
||||
val distortedSegments = shapeContour.segments.map {
|
||||
val c = it.cubic
|
||||
|
||||
Reference in New Issue
Block a user