[orx-shapes] Add geometric arrangement together with two demos. (#324)

This commit is contained in:
Steven van den Broek
2024-01-02 20:45:11 +01:00
committed by GitHub
parent 3b57c3ce26
commit 2fb2b11180
4 changed files with 571 additions and 0 deletions

View File

@@ -0,0 +1,82 @@
import org.openrndr.application
import org.openrndr.color.ColorRGBa
import org.openrndr.extra.color.spaces.ColorOKHSVa
import org.openrndr.extra.shapes.Arrangement
import org.openrndr.extra.shapes.hobbyCurve
import org.openrndr.math.Vector2
import org.openrndr.shape.Circle
import org.openrndr.shape.LineSegment
import org.openrndr.shape.Rectangle
import org.openrndr.shape.Shape
import kotlin.random.Random
fun main() = application {
configure {
width = 800
height = 800
}
program {
// Create some shapes
val outer = Circle(drawer.bounds.center, 200.0)
val inner = Circle(drawer.bounds.center, 150.0)
val annulus = Shape(listOf(outer.contour.clockwise, inner.contour.counterClockwise))
val rectangle = Rectangle.fromCenter(drawer.bounds.center, 200.0, 400.0)
val line = LineSegment(100.0, 400.0, 700.0, 400.0)
val circle2 = Circle(200.0, 300.0, 100.0)
val hobbyPts = listOf(
Vector2(750.0, 100.0),
Vector2(700.0, 300.0),
Vector2(600.0, 350.0),
Vector2(450.0, 450.0),
Vector2(475.0, 200.0),
)
val hobby = hobbyCurve(hobbyPts, closed=true)
val lineBelow = hobbyCurve(listOf(
Vector2(100.0, 700.0),
Vector2(300.0, 725.0),
Vector2(500.0, 675.0),
Vector2(700.0, 700.0),
))
val circleAbove = Circle(100.0, 100.0, 50.0)
// Construct an arrangement
val arrangement = Arrangement(annulus, rectangle, circle2, hobby, line, lineBelow, circleAbove)
extend {
drawer.apply {
clear(ColorRGBa.WHITE)
// Draw the faces that originate from (are a subset of) some input shape
val faces = arrangement.originFaces
for ((i, f) in faces.shuffled(Random(0)).withIndex()) {
stroke = null
fill = ColorOKHSVa(i * 360.0 / faces.size, 0.75, 1.0).toRGBa()
contour(f.contour)
}
// Draw the edges
for (e in arrangement.edges) {
strokeWeight = 2.0
stroke = ColorRGBa.BLACK
fill = null
contour(e.contour)
}
// Thicken the outer boundaries of each connected component and the 'holes' of the arrangement.
// Holes are faces that are not a subset of an input shape.
strokeWeight = 4.0
contours(arrangement.boundaries)
contours(arrangement.holes.map { it.contour })
// Draw the vertices
for (v in arrangement.vertices) {
strokeWeight = 2.5
stroke = ColorRGBa.BLACK
fill = ColorRGBa.WHITE
circle(v.pos, 6.0)
}
}
}
}
}

View File

@@ -0,0 +1,99 @@
import org.openrndr.application
import org.openrndr.color.ColorRGBa
import org.openrndr.draw.isolated
import org.openrndr.extra.color.spaces.ColorOKHSVa
import org.openrndr.extra.noise.poissonDiskSampling
import org.openrndr.extra.shapes.Arrangement
import org.openrndr.extra.shapes.BoundedFace
import org.openrndr.extra.shapes.hobbyCurve
import kotlin.random.Random
fun main() = application {
configure {
width = 800
height = 800
}
program {
// Create a nice curve that intersects itself
val uniformPoints = poissonDiskSampling(drawer.bounds.offsetEdges(-200.0), 100.0, random=Random(10579))
val curve = hobbyCurve(uniformPoints, closed=true)
// Construct an arrangement of the curve. In order to obtain an arrangement dealing with self intersections,
// the curve is passed in twice.
val arrangement = Arrangement(curve, curve)
// We will color each bounded face.
val faces = arrangement.boundedFaces
val colors = faces.withIndex().associate { (i, f) ->
f to ColorOKHSVa(i * 360.0 / faces.size, 0.75, 1.0).toRGBa()
}
extend {
drawer.apply {
clear(ColorRGBa.WHITE)
isolated {
// Shrink the drawing
translate(drawer.bounds.center)
scale(0.5)
translate(-drawer.bounds.center)
// Draw each face
stroke = null
for (f in faces) {
fill = colors[f]
contour(f.contour)
}
// Draw the curve on top
fill = null
stroke = ColorRGBa.BLACK
strokeWeight = 4.0
contour(curve)
strokeWeight = 4.0
stroke = ColorRGBa.BLACK
fill = ColorRGBa.WHITE
circles(arrangement.vertices.map { it.pos }, 12.0)
}
// We are going to draw the neighborhood of each vertex in the arrangement
for (v in arrangement.vertices) {
isolated {
// Shrink the drawing quite a bit
translate(v.pos)
scale(0.35)
translate(-v.pos)
// Move the drawing in the direction of the vertex
translate((v.pos - drawer.bounds.center).normalized * 300.0)
// For each outgoing half-edge, draw the associated face
for (e in v.outgoing) {
val f = e.face as? BoundedFace
if (f != null) {
stroke = null
fill = colors[f]!!.opacify(0.5)
contour(f.contour)
}
}
// For each outgoing half-edge, draw the edge
for (e in v.outgoing) {
strokeWeight = 2.0/0.35
stroke = ColorRGBa.BLACK
contour(e.contour)
}
// Draw the vertex
strokeWeight = 2 / 0.35
stroke = ColorRGBa.BLACK
fill = ColorRGBa.WHITE
circle(v.pos, 6.0 / 0.35)
}
}
}
}
}
}