[orx-palette] Add ColorBrewer2, demos, update README (#363)
This commit is contained in:
@@ -43,7 +43,7 @@ To make use of these extensions clone the [OPENRNDR template](https://github.com
|
|||||||
| [`orx-no-clear`](orx-no-clear/) | Provides the classical "draw-without-clearing-the-screen" functionality. |
|
| [`orx-no-clear`](orx-no-clear/) | Provides the classical "draw-without-clearing-the-screen" functionality. |
|
||||||
| [`orx-noise`](orx-noise/) | Randomness for every type of person: Perlin, uniform, value, simplex, fractal and many other types of noise. |
|
| [`orx-noise`](orx-noise/) | Randomness for every type of person: Perlin, uniform, value, simplex, fractal and many other types of noise. |
|
||||||
| [`orx-obj-loader`](orx-obj-loader/) | Simple loader and saver for Wavefront .obj 3D mesh files. |
|
| [`orx-obj-loader`](orx-obj-loader/) | Simple loader and saver for Wavefront .obj 3D mesh files. |
|
||||||
| [`orx-palette`](orx-palette/) | Provides hundreds of color palettes. |
|
| [`orx-palette`](orx-palette/) | Collections of color palettes and tools for interacting with them. |
|
||||||
| [`orx-parameters`](orx-parameters/) | Provides annotations and tools for turning Kotlin properties into introspectable parameters. Used by [`orx-gui`](../orx-jvm/orx-gui/README.md) to automatically generate user interfaces. |
|
| [`orx-parameters`](orx-parameters/) | Provides annotations and tools for turning Kotlin properties into introspectable parameters. Used by [`orx-gui`](../orx-jvm/orx-gui/README.md) to automatically generate user interfaces. |
|
||||||
| [`orx-property-watchers`](orx-property-watchers/) | Tools for setting up property watcher based pipelines |
|
| [`orx-property-watchers`](orx-property-watchers/) | Tools for setting up property watcher based pipelines |
|
||||||
| [`orx-quadtree`](orx-quadtree/) | A [Quadtree](https://en.wikipedia.org/wiki/Quadtree) is a spatial partioning tree structure meant to provide fast spatial queries such as nearest points within a range. |
|
| [`orx-quadtree`](orx-quadtree/) | A [Quadtree](https://en.wikipedia.org/wiki/Quadtree) is a spatial partioning tree structure meant to provide fast spatial queries such as nearest points within a range. |
|
||||||
|
|||||||
@@ -1,12 +1,44 @@
|
|||||||
# orx-palette
|
# orx-palette
|
||||||
|
|
||||||
Provides hundreds of color palettes.
|
Collections of color palettes and tools for interacting with them.
|
||||||
|
|
||||||
## Usage
|
Find demos in the demo folder.
|
||||||
|
|
||||||
|
## ColorBrewer2
|
||||||
|
|
||||||
|
A collection of color palettes based on the research of Dr. Cynthia Brewer. Explore them live at [colorbrewer2.org](https://colorbrewer2.org/).
|
||||||
|
|
||||||
|
Each Palette has between 3 and 11 colors.
|
||||||
|
|
||||||
|
Use `colorBrewer2Palettes()` to query and obtain a list of `ColorBrewer2Palette` instances.
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
import org.openrndr.extra.palette.PaletteStudio
|
// all palettes
|
||||||
|
val palettes = colorBrewer2Palettes()
|
||||||
|
|
||||||
|
// palettes with 5 colors
|
||||||
|
val palettes = colorBrewer2Palettes(numberOfColors = 5)
|
||||||
|
|
||||||
|
// palettes of type Sequential
|
||||||
|
val palettes = colorBrewer2Palettes(palettetype = ColorBrewer2Type.Sequential)
|
||||||
|
```
|
||||||
|
|
||||||
|
Once we have some palettes, we can pick one and use its colors:
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
palettes.first().colors.forEachIndexed { i, color ->
|
||||||
|
drawer.fill = color
|
||||||
|
drawer.circle(drawer.bounds.center, 300.0 - i * 40.0)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Palette Studio
|
||||||
|
|
||||||
|
A class to load palette collections from JSON files, load random palettes and sort colors. JVM only.
|
||||||
|
|
||||||
|
### Usage
|
||||||
|
|
||||||
|
```kotlin
|
||||||
val paletteStudio = PaletteStudio(
|
val paletteStudio = PaletteStudio(
|
||||||
loadDefault = true, // Loads the first collection of palettes. [default -> true]
|
loadDefault = true, // Loads the first collection of palettes. [default -> true]
|
||||||
sortBy = PaletteStudio.SortBy.DARKEST, // Sorts the colors by luminance. [default -> PaletteStudio.SortBy.NO_SORTING]
|
sortBy = PaletteStudio.SortBy.DARKEST, // Sorts the colors by luminance. [default -> PaletteStudio.SortBy.NO_SORTING]
|
||||||
@@ -28,13 +60,13 @@ paletteStudio.randomPalette()
|
|||||||
paletteStudio.randomize()
|
paletteStudio.randomize()
|
||||||
|
|
||||||
// changes the collection of palettes
|
// changes the collection of palettes
|
||||||
paletteStudio.changeCollection(PaletteStudio.Collections.TWO)
|
paletteStudio.loadCollection(PaletteStudio.Collections.TWO)
|
||||||
|
|
||||||
// load your own from a JSON file with a structure of Array<Array<String>>
|
// load your own from a JSON file with a structure of Array<Array<String>>
|
||||||
paletteStudio.loadExternal("data/palette-autumn.json")
|
paletteStudio.loadExternal("data/palette-autumn.json")
|
||||||
```
|
```
|
||||||
|
|
||||||
### Keybindings
|
#### Keybindings
|
||||||
|
|
||||||
Keybindings for getting a random palette (`l`) and randomizing (`k`) one can be set easily by declaring inside the `program`:
|
Keybindings for getting a random palette (`l`) and randomizing (`k`) one can be set easily by declaring inside the `program`:
|
||||||
```kotlin
|
```kotlin
|
||||||
@@ -42,65 +74,29 @@ val paletteStudio = PaletteStudio()
|
|||||||
|
|
||||||
extend(paletteStudio)
|
extend(paletteStudio)
|
||||||
```
|
```
|
||||||
|
<!-- __demos__ -->
|
||||||
|
## Demos
|
||||||
|
### DemoColorBrewer2_01
|
||||||
|
[source code](src/jvmDemo/kotlin/DemoColorBrewer2_01.kt)
|
||||||
|
|
||||||
## Example
|

|
||||||
|
|
||||||
```kotlin
|
### DemoColorBrewer2_02
|
||||||
fun main() = application {
|
[source code](src/jvmDemo/kotlin/DemoColorBrewer2_02.kt)
|
||||||
configure {
|
|
||||||
title = "Palette"
|
|
||||||
width = 720
|
|
||||||
height = 720
|
|
||||||
}
|
|
||||||
program {
|
|
||||||
val colors = mutableListOf<ColorRGBa>()
|
|
||||||
|
|
||||||
fun fillColors() {
|

|
||||||
for (n in 0..36) {
|
|
||||||
when(n) {
|
|
||||||
12 -> paletteStudio.changeCollection(PaletteStudio.Collections.TWO)
|
|
||||||
24 -> paletteStudio.changeCollection(PaletteStudio.Collections.THREE)
|
|
||||||
}
|
|
||||||
|
|
||||||
val color = Random.pick(paletteStudio.colors!!)
|
### DemoColorBrewer2_03
|
||||||
|
[source code](src/jvmDemo/kotlin/DemoColorBrewer2_03.kt)
|
||||||
|
|
||||||
colors.add(color)
|

|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
keyboard.keyDown.listen {
|
### DemoPaletteStudio01
|
||||||
if (it.name == "c") {
|
[source code](src/jvmDemo/kotlin/DemoPaletteStudio01.kt)
|
||||||
colors.clear()
|
|
||||||
fillColors()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fillColors()
|

|
||||||
|
|
||||||
extend() {
|
### DemoPaletteStudio02
|
||||||
drawer.background(paletteStudio.background)
|
[source code](src/jvmDemo/kotlin/DemoPaletteStudio02.kt)
|
||||||
|
|
||||||
val size = 120.0
|

|
||||||
val radius = size / 2.0
|
|
||||||
|
|
||||||
for (x in 0 until 6) {
|
|
||||||
for (y in 0 until 6) {
|
|
||||||
val index = x + y * 6
|
|
||||||
val color = colors[index]
|
|
||||||
val x = size * x
|
|
||||||
val y = size * y
|
|
||||||
|
|
||||||
drawer.fill = color
|
|
||||||
drawer.stroke = color
|
|
||||||
|
|
||||||
if (index <= 11 || index > 23) {
|
|
||||||
drawer.circle(x + radius, y + radius, radius)
|
|
||||||
} else {
|
|
||||||
drawer.rectangle(x, y, size, size)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|||||||
@@ -1,10 +1,28 @@
|
|||||||
plugins {
|
plugins {
|
||||||
org.openrndr.extra.convention.`kotlin-jvm`
|
org.openrndr.extra.convention.`kotlin-multiplatform`
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
kotlin {
|
||||||
implementation(libs.gson)
|
sourceSets {
|
||||||
implementation(project(":orx-noise"))
|
val commonMain by getting {
|
||||||
implementation(libs.openrndr.application)
|
dependencies {
|
||||||
implementation(libs.openrndr.math)
|
implementation(libs.openrndr.application)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
val jvmMain by getting {
|
||||||
|
dependencies {
|
||||||
|
implementation(project(":orx-noise"))
|
||||||
|
implementation(libs.gson)
|
||||||
|
implementation(libs.openrndr.math)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val jvmDemo by getting {
|
||||||
|
dependencies {
|
||||||
|
implementation(project(":orx-palette"))
|
||||||
|
implementation(project(":orx-palette"))
|
||||||
|
implementation(project(":orx-shapes"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
2777
orx-palette/src/commonMain/kotlin/ColorBrewer2.kt
Normal file
2777
orx-palette/src/commonMain/kotlin/ColorBrewer2.kt
Normal file
File diff suppressed because it is too large
Load Diff
22
orx-palette/src/jvmDemo/kotlin/DemoColorBrewer2_01.kt
Normal file
22
orx-palette/src/jvmDemo/kotlin/DemoColorBrewer2_01.kt
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import org.openrndr.application
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Demonstrates how to use a ColorBrewer2 palette.
|
||||||
|
* Finds the first available palette with 5 colors,
|
||||||
|
* then draws concentric circles filled with those colors.
|
||||||
|
*/
|
||||||
|
fun main() = application {
|
||||||
|
configure {
|
||||||
|
width = 720
|
||||||
|
height = 720
|
||||||
|
}
|
||||||
|
program {
|
||||||
|
val palette = colorBrewer2Palettes(numberOfColors = 5).first().colors
|
||||||
|
extend {
|
||||||
|
palette.forEachIndexed { i, color ->
|
||||||
|
drawer.fill = color
|
||||||
|
drawer.circle(drawer.bounds.center, 300.0 - i * 40.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
41
orx-palette/src/jvmDemo/kotlin/DemoColorBrewer2_02.kt
Normal file
41
orx-palette/src/jvmDemo/kotlin/DemoColorBrewer2_02.kt
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
import org.openrndr.application
|
||||||
|
import org.openrndr.color.ColorRGBa
|
||||||
|
import org.openrndr.extra.shapes.primitives.Arc
|
||||||
|
import org.openrndr.extra.shapes.primitives.grid
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visualizes the ColorBrewer2 color palettes with 8 colors as circles
|
||||||
|
* made of colored arcs.
|
||||||
|
*/
|
||||||
|
fun main() = application {
|
||||||
|
configure {
|
||||||
|
width = 720
|
||||||
|
height = 720
|
||||||
|
}
|
||||||
|
program {
|
||||||
|
val palettes = colorBrewer2Palettes(numberOfColors = 8)
|
||||||
|
// Make a grid and discard some cells if there are more cells than palettes
|
||||||
|
val grid = drawer.bounds.grid(6, 6).flatten().take(palettes.size)
|
||||||
|
extend {
|
||||||
|
drawer.clear(ColorRGBa.WHITE)
|
||||||
|
// For each grid cell
|
||||||
|
grid.forEachIndexed { i, rect ->
|
||||||
|
// Find the corresponding palette
|
||||||
|
val palette = palettes[i].colors
|
||||||
|
// And display its colors on thick arcs
|
||||||
|
palette.forEachIndexed { ci, color ->
|
||||||
|
drawer.strokeWeight = 15.0
|
||||||
|
drawer.stroke = color
|
||||||
|
drawer.fill = null
|
||||||
|
drawer.contour(
|
||||||
|
Arc(
|
||||||
|
rect.center, rect.width * 0.35,
|
||||||
|
360.0 * (ci + 0.0) / palette.size,
|
||||||
|
360.0 * (ci + 1.0) / palette.size
|
||||||
|
).contour
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
38
orx-palette/src/jvmDemo/kotlin/DemoColorBrewer2_03.kt
Normal file
38
orx-palette/src/jvmDemo/kotlin/DemoColorBrewer2_03.kt
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
import org.openrndr.application
|
||||||
|
import org.openrndr.color.ColorRGBa
|
||||||
|
import org.openrndr.extra.shapes.primitives.Arc
|
||||||
|
import org.openrndr.extra.shapes.primitives.grid
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visualizes 49 ColorBrewer2 color palettes of type "Diverging" as circles
|
||||||
|
* made of colored arcs. Since there are more palettes than grid cells,
|
||||||
|
* not all palettes are visualized.
|
||||||
|
*/
|
||||||
|
fun main() = application {
|
||||||
|
configure {
|
||||||
|
width = 720
|
||||||
|
height = 720
|
||||||
|
}
|
||||||
|
program {
|
||||||
|
val palettes = colorBrewer2Palettes(paletteType = ColorBrewer2Type.Diverging)
|
||||||
|
val grid = drawer.bounds.grid(7, 7).flatten().take(palettes.size)
|
||||||
|
extend {
|
||||||
|
drawer.clear(ColorRGBa.WHITE)
|
||||||
|
grid.forEachIndexed { i, rect ->
|
||||||
|
val palette = palettes[i].colors
|
||||||
|
palette.forEachIndexed { ci, color ->
|
||||||
|
drawer.strokeWeight = 15.0
|
||||||
|
drawer.stroke = color
|
||||||
|
drawer.fill = null
|
||||||
|
drawer.contour(
|
||||||
|
Arc(
|
||||||
|
rect.center, rect.width * 0.4,
|
||||||
|
360.0 * (ci + 0.0) / palette.size,
|
||||||
|
360.0 * (ci + 1.0) / palette.size
|
||||||
|
).contour
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
31
orx-palette/src/jvmDemo/kotlin/DemoPaletteStudio01.kt
Normal file
31
orx-palette/src/jvmDemo/kotlin/DemoPaletteStudio01.kt
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import org.openrndr.application
|
||||||
|
import org.openrndr.extra.palette.PaletteStudio
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Demonstrates how to access palette colors using PaletteStudio.
|
||||||
|
* A new random palette is loaded every 60 animation frames.
|
||||||
|
*/
|
||||||
|
fun main() = application {
|
||||||
|
configure {
|
||||||
|
width = 720
|
||||||
|
height = 720
|
||||||
|
}
|
||||||
|
program {
|
||||||
|
val paletteStudio = PaletteStudio()
|
||||||
|
|
||||||
|
// Choose a specific initial palette
|
||||||
|
paletteStudio.select(11)
|
||||||
|
|
||||||
|
extend {
|
||||||
|
if(frameCount % 60 == 50) {
|
||||||
|
paletteStudio.randomPalette()
|
||||||
|
}
|
||||||
|
drawer.clear(paletteStudio.background)
|
||||||
|
|
||||||
|
paletteStudio.colors2.forEachIndexed { i, color ->
|
||||||
|
drawer.fill = color
|
||||||
|
drawer.circle(drawer.bounds.center, 300.0 - i * 40.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
68
orx-palette/src/jvmDemo/kotlin/DemoPaletteStudio02.kt
Normal file
68
orx-palette/src/jvmDemo/kotlin/DemoPaletteStudio02.kt
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
import org.openrndr.application
|
||||||
|
import org.openrndr.color.ColorRGBa
|
||||||
|
import org.openrndr.extra.palette.PaletteStudio
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Demonstrates how to create a design using PaletteStudio.
|
||||||
|
* Press the `c` key to load a random palette.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
fun main() = application {
|
||||||
|
configure {
|
||||||
|
title = "Palette"
|
||||||
|
width = 720
|
||||||
|
height = 720
|
||||||
|
}
|
||||||
|
program {
|
||||||
|
val paletteStudio = PaletteStudio()
|
||||||
|
|
||||||
|
val colors = mutableListOf<ColorRGBa>()
|
||||||
|
|
||||||
|
fun fillColors() {
|
||||||
|
for (n in 0..36) {
|
||||||
|
when (n) {
|
||||||
|
12 -> paletteStudio.loadCollection(PaletteStudio.Collections.TWO)
|
||||||
|
24 -> paletteStudio.loadCollection(PaletteStudio.Collections.THREE)
|
||||||
|
}
|
||||||
|
|
||||||
|
val color = paletteStudio.colors.random()
|
||||||
|
|
||||||
|
colors.add(color)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
keyboard.keyDown.listen {
|
||||||
|
if (it.name == "c") {
|
||||||
|
colors.clear()
|
||||||
|
fillColors()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fillColors()
|
||||||
|
|
||||||
|
extend {
|
||||||
|
drawer.clear(paletteStudio.background)
|
||||||
|
|
||||||
|
val size = 120.0
|
||||||
|
val radius = size / 2.0
|
||||||
|
|
||||||
|
for (x in 0 until 6) {
|
||||||
|
for (y in 0 until 6) {
|
||||||
|
val index = x + y * 6
|
||||||
|
val color = colors[index]
|
||||||
|
val x = size * x
|
||||||
|
val y = size * y
|
||||||
|
|
||||||
|
drawer.fill = color
|
||||||
|
drawer.stroke = color
|
||||||
|
|
||||||
|
if (index <= 11 || index > 23) {
|
||||||
|
drawer.circle(x + radius, y + radius, radius)
|
||||||
|
} else {
|
||||||
|
drawer.rectangle(x, y, size, size)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user