Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
uellenberg committed Apr 1, 2022
2 parents fe0274b + 250b90c commit 61721e4
Show file tree
Hide file tree
Showing 10 changed files with 169 additions and 22 deletions.
4 changes: 4 additions & 0 deletions examples/domain-coloring/README.md
Original file line number Diff line number Diff line change
@@ -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).
7 changes: 7 additions & 0 deletions examples/domain-coloring/background.lm
Original file line number Diff line number Diff line change
@@ -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));
25 changes: 25 additions & 0 deletions examples/domain-coloring/color.lm
Original file line number Diff line number Diff line change
@@ -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);
});
}
17 changes: 17 additions & 0 deletions examples/domain-coloring/display.lm
Original file line number Diff line number Diff line change
@@ -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);
19 changes: 19 additions & 0 deletions examples/domain-coloring/function.lm
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
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);
}
27 changes: 27 additions & 0 deletions examples/domain-coloring/main.lm
Original file line number Diff line number Diff line change
@@ -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");
16 changes: 16 additions & 0 deletions examples/domain-coloring/rendering.lm
Original file line number Diff line number Diff line change
@@ -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)]);
});
}
38 changes: 36 additions & 2 deletions examples/mandelbrot/display.lm
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand All @@ -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);
});
7 changes: 5 additions & 2 deletions examples/mandelbrot/main.lm
Original file line number Diff line number Diff line change
@@ -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;

Expand Down
31 changes: 13 additions & 18 deletions examples/mandelbrot/mandelbrot.lm
Original file line number Diff line number Diff line change
@@ -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.
Expand All @@ -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.
Expand All @@ -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).
Expand All @@ -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])
})
}
}

export gSet;
export calculate;

0 comments on commit 61721e4

Please sign in to comment.