From 1029772cebe47119f7386976155d577e9e64efa1 Mon Sep 17 00:00:00 2001 From: uellenberg Date: Thu, 31 Mar 2022 23:38:06 -0700 Subject: [PATCH 1/2] Added domain coloring --- examples/domain-coloring/README.md | 4 +++ examples/domain-coloring/background.lm | 7 +++++ examples/domain-coloring/color.lm | 25 +++++++++++++++++ examples/domain-coloring/display.lm | 17 ++++++++++++ examples/domain-coloring/function.lm | 21 ++++++++++++++ examples/domain-coloring/main.lm | 27 ++++++++++++++++++ examples/domain-coloring/rendering.lm | 16 +++++++++++ examples/mandelbrot/display.lm | 38 ++++++++++++++++++++++++-- examples/mandelbrot/main.lm | 7 +++-- examples/mandelbrot/mandelbrot.lm | 31 +++++++++------------ 10 files changed, 171 insertions(+), 22 deletions(-) create mode 100644 examples/domain-coloring/README.md create mode 100644 examples/domain-coloring/background.lm create mode 100644 examples/domain-coloring/color.lm create mode 100644 examples/domain-coloring/display.lm create mode 100644 examples/domain-coloring/function.lm create mode 100644 examples/domain-coloring/main.lm create mode 100644 examples/domain-coloring/rendering.lm diff --git a/examples/domain-coloring/README.md b/examples/domain-coloring/README.md new file mode 100644 index 0000000..911a3e0 --- /dev/null +++ b/examples/domain-coloring/README.md @@ -0,0 +1,4 @@ +# Domain Coloring +This example plots complex functions using color. Open [main.lm](main.lm) to configure. + +NOTICE: This requires a post-processor to display correctly. It is recommended that you compile this using [Graphgame Studio](https://graphgame.js.org). \ No newline at end of file diff --git a/examples/domain-coloring/background.lm b/examples/domain-coloring/background.lm new file mode 100644 index 0000000..6288342 --- /dev/null +++ b/examples/domain-coloring/background.lm @@ -0,0 +1,7 @@ +//Create a black background. +export const b_lack = rgb(0, 0, 0); + +display fill = 1; +display thickness = 0; +display color = b_lack; +polygon((-.5, -.5), (.5, -.5), (.5, .5), (-.5, .5)); \ No newline at end of file diff --git a/examples/domain-coloring/color.lm b/examples/domain-coloring/color.lm new file mode 100644 index 0000000..9c860c1 --- /dev/null +++ b/examples/domain-coloring/color.lm @@ -0,0 +1,25 @@ +export function c_olor(x) { + const h = cArg(x) * (180/pi); + const s = 1/(1 + .3*log(cAbs(x) + 1)) - .4; + const l = 1 - 1/(1.1 + 5*log(cAbs(x) + 1)); + + state = hsv(h, s, l); +} + +inline function gColor(num) { + //Loop through the image, divided by the number of splits we turn the image into (this creates a single split). + state = range(1, width * height/get!(SPLITS)).map(idx => { + //Get the x-position, centered at (0, 0). + const x = conv_1d_2d_x(idx, width) - width/2; + //Gets the y-position, centered at (0,0) and increased by the y-position of previous splits. + const y = conv_1d_2d_y(idx, width) - height/2 + height*(num-1)/get!(SPLITS); + + const cX = x/r_es + x_off; + const cY = y/r_es + y_off; + const cVal = (cX, cY); + + const val = i_t(cVal); + + state = c_olor(val); + }); +} \ No newline at end of file diff --git a/examples/domain-coloring/display.lm b/examples/domain-coloring/display.lm new file mode 100644 index 0000000..82ae9a0 --- /dev/null +++ b/examples/domain-coloring/display.lm @@ -0,0 +1,17 @@ +//This file handles displaying the fractal, and putting together the set, color handler, and renderer. + +//The way that splitting works is we split up out final big image into multiple smaller ones, to avoid hitting Desmos' limit. We must define the amount of splits (or number of smaller images) below, and also define the images themselves. + +define!(SPLIT_NUM, 1); + +iterate!({ + display thickness = 0; + export const "c_olor${get!(SPLIT_NUM)}" = gColor(get!(SPLIT_NUM)); + + display fill = 1; + display thickness = 0; + display color = "c_olor${get!(SPLIT_NUM)}"; + expression => gRender(get!(SPLIT_NUM)); + + define!(SPLIT_NUM, SPLIT_NUM + 1); +}, SPLITS); diff --git a/examples/domain-coloring/function.lm b/examples/domain-coloring/function.lm new file mode 100644 index 0000000..e1770da --- /dev/null +++ b/examples/domain-coloring/function.lm @@ -0,0 +1,21 @@ +import!("util.lm"); + +export cPow; +export cPolar; +export cMul; +export cSin; + +export const a = 0; +export const p_oint = (a, a - 3); + +export function r_un(x) { + cSin(cPow(x, p_oint)) +} + +export function i_t(x) { + state = p_oint; + + iterate!({ + state = cSin(cPow(x, state)); + }, ITERATIONS); +} \ No newline at end of file diff --git a/examples/domain-coloring/main.lm b/examples/domain-coloring/main.lm new file mode 100644 index 0000000..b1ddd07 --- /dev/null +++ b/examples/domain-coloring/main.lm @@ -0,0 +1,27 @@ +inline const width = 100; +inline const height = 100; + +export const r_es = width/2 * 1/5; + +export const x_off = 0; +export const y_off = 0; + +//Defines the number of iterations to use. +define!(ITERATIONS, 5); + +//Defines the amount of "splits" to use. For a 200x200 image, you need 4 splits (200*200 / 10,000 = 4). +//This will create 4 images with 10,000 pixels each, which will be placed together to form a complete image. +define!(SPLITS, 1); + +//Import everything. + +//First, add a background. +import!("background.lm"); +//Next, make it possible to compute the Mandelbrot set. +import!("function.lm"); +//After that, use the Mandelbrot set to compute the colors. +import!("color.lm"); +//Create an object that the colors can be applied to. +import!("rendering.lm"); +//Use the methods defined above to display everything. +import!("display.lm"); \ No newline at end of file diff --git a/examples/domain-coloring/rendering.lm b/examples/domain-coloring/rendering.lm new file mode 100644 index 0000000..9faf8cc --- /dev/null +++ b/examples/domain-coloring/rendering.lm @@ -0,0 +1,16 @@ +//This file is responsible for creating the polygons that are used for rendering. Rendering in Desmos is fairly simple: we just need to create a polygon list that fills up the square. The actual coloring of this set of polygons is up to the color handler. + +//Renders the image. This just creates a grid of polygons. +inline function gRender(num) { + //Loop through the image, divided by the number of splits we turn the image into (this creates a single split). + state = range(1, width * height/get!(SPLITS)).map(idx => { + //Get the x-position, centered at (0, 0). + const x = conv_1d_2d_x(idx, width) - width/2; + //Gets the y-position, centered at (0,0) and increased by the y-position of previous splits. + const y = conv_1d_2d_y(idx, width) - height/2 + height*(num-1)/get!(SPLITS); + + //Create a polygon using the x and y position. + //This is slightly bigger than 1x1 to remove grid lines that 1x1 creates. + state = polygon((x/width, y/height) + [(-.2/width, -.2/height), (-.2/width, 1.2/height), (1.2/width, 1.2/height), (1.2/width, -.2/height)]); + }); +} \ No newline at end of file diff --git a/examples/mandelbrot/display.lm b/examples/mandelbrot/display.lm index 77260c0..9ab55f5 100644 --- a/examples/mandelbrot/display.lm +++ b/examples/mandelbrot/display.lm @@ -2,7 +2,7 @@ //The way that splitting works is we split up out final big image into multiple smaller ones, to avoid hitting Desmos' limit. We must define the amount of splits (or number of smaller images) below, and also define the images themselves. -define!(SPLIT_NUM, 1); +/*define!(SPLIT_NUM, 1); iterate!({ export const "s_et${get!(SPLIT_NUM)}" = gSet(get!(SPLIT_NUM)); @@ -16,4 +16,38 @@ iterate!({ expression => gRender(get!(SPLIT_NUM)); define!(SPLIT_NUM, SPLIT_NUM + 1); -}, SPLITS); +}, SPLITS);*/ + +//Create a behavior for our renderer. +createBehavior!("display", { + setValArgs!("num", 0); + + behaviorCustom!({ + display fill = 1; + display thickness = 0; + display color = "c_olor${getVal!("num")}"; + expression => getVal!("set"); + }); + + setVal!("set", { + range(1, width * height/get!(SPLITS)).map(idx => { + (0, pack(0, 0, pack_digits)) + }) + }); + setMut!("set"); + + /*setValAction!("set", { + gSet(getVal!("num"), set) + });*/ + + setVal!("color", 0); + setMut!("color"); + + /*setValAction!("color", { + gColor(getVal!("num"), getVal!("set")) + });*/ +}); + +createObject!({ + useBehavior!("display", 1); +}); \ No newline at end of file diff --git a/examples/mandelbrot/main.lm b/examples/mandelbrot/main.lm index d69f492..b6a77d0 100644 --- a/examples/mandelbrot/main.lm +++ b/examples/mandelbrot/main.lm @@ -1,8 +1,11 @@ //This file creates a rendering of the Mandelbrot set. It works by computing the number of iterations that each pixel takes to generate, then using that iteration number to color it based on a gradient. //Due to Desmos' limitations, only a 100x100 (10,000 element) grid of pixels is possible. This program gets around that by creating 4 200x50 strips of pixels (or whatever you have it configured to). -inline const width = 100; -inline const height = 100; +import templates from "graphgame"; +initialize!(); + +inline const width = 10; +inline const height = 10; export const r_es = width/2 * 50; diff --git a/examples/mandelbrot/mandelbrot.lm b/examples/mandelbrot/mandelbrot.lm index a94097f..fb6f0c1 100644 --- a/examples/mandelbrot/mandelbrot.lm +++ b/examples/mandelbrot/mandelbrot.lm @@ -1,5 +1,11 @@ //This file contains the code used to compute the fractal itself. The values generated from here are then passed on to the renderer. +//This exports our functions to make things more efficient. +export pack; +export unpackFloat; +export unpackInt; +export cMul; + inline const pack_digits = 6; //Computes one iteration. @@ -8,7 +14,7 @@ export function i_t(x, y, c) { const iterations = unpackInt(c.y, pack_digits); //If we've exceeded the maximum size, don't run any more iterations and just return the current value. - if(distance(cPoint, (0, 0)) >= max_size) { + if(cAbs(cPoint) >= max_size) { c } else { //Run another iteration (z*z + x + yi) and increment the iteration count. @@ -34,22 +40,8 @@ export function f_rac(v) { iterations + 1 - log_2(log(cAbs(cPoint))) } -//Find the iteration count for a point. -inline function calculate(x, y) { - //Initialize it. The first number is the x-position, and the second is the y-position and iteration count packed together. - state = (0, pack(0, 0, pack_digits)); - - //Run the iteration function on it for as many times as specified. - iterate!({ - state = i_t10(x, y, state); - }, ITERATIONS); - - //Turn the point and iteration count into a fractional iteration count. - f_rac(state) -} - //Generates a set for a specific row. -inline function gSet(num) { +inline function gSet(num, set) { //Loop through the image, divided by the number of splits we turn the image into (this creates a single split). range(1, width * height/get!(SPLITS)).map(idx => { //Get the x-position, centered at (0, 0). @@ -58,6 +50,9 @@ inline function gSet(num) { const y = conv_1d_2d_y(idx, width) - height/2 + height*(num-1)/get!(SPLITS); //Calculate the iteration count. - calculate(x/r_es + x_off, y/r_es + y_off) + i_t(x/r_es + x_off, y/r_es + y_off, set[idx]) }) -} \ No newline at end of file +} + +export gSet; +export calculate; \ No newline at end of file From 250b90c43d0d4e94672e05b2707dd83c8f3bac21 Mon Sep 17 00:00:00 2001 From: uellenberg Date: Thu, 31 Mar 2022 23:55:44 -0700 Subject: [PATCH 2/2] Fix domain coloring --- examples/domain-coloring/function.lm | 2 -- 1 file changed, 2 deletions(-) diff --git a/examples/domain-coloring/function.lm b/examples/domain-coloring/function.lm index e1770da..c8f9023 100644 --- a/examples/domain-coloring/function.lm +++ b/examples/domain-coloring/function.lm @@ -1,5 +1,3 @@ -import!("util.lm"); - export cPow; export cPolar; export cMul;