title

deconbatch's Land of 1000 Creative Codings. example codes of Processing / p5.js, how-to articles, generative art images, and much more!

Generative formula that generates generative art?

Generative art made with p5.js.
Generative art made with p5.js.

You can try to run the code.





Description.


When I've been playing with Vector Field, I tried various formulas to calculate x, y coordinates.
// example
x1 += div * (sin(TWO_PI * y0 * multA) - cos(TWO_PI * x0 * multC));
y1 += div * (sin(TWO_PI * x0 * multB) - cos(TWO_PI * y0 * multD));


And I thought If I can dream of ten thousand or more formulas.
That'll create various patterns I've never seen, and it must be fun!

But how...

Computer!
I can make a computer to do mass calculation.
So I must be able to make my computer generate tons of formula.

I found Function constructor in JavaScript makes my dream come true.
Function - JavaScript | MDN
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function

This time, I constructed the function that has two arguments and returns one calculated value.
// example
Function(arg01, arg02, 'let result = cos(arg01) + sin(arg02); return result;');

And I should generate 'cos(arg01) + sin(arg02)' part.

I chose '+, - , *, %' as operators. I didn't use '/' to avoid zero-divide.
I defined them as a string array and chose one randomly.
const oprts = [' + ', ' - ', ' * ', ' % '];
oprts[floor(random(oprts.length))];


I defined two arguments and mathematical methods in the same way.
And I used the 'replace' method to replace the argument that randomly chosen.
// example : sin({p}) -> sin(_a)
funcs[floor(random(funcs.length))].replace(/\{p\}/, parms[floor(random(parms.length))]);



Creative coding that creates the code!
You can see the whole code below.

p5.js example code.

Please feel free to use it, if you like it.
To see other works based on my code is my pleasure. And my honor.



<html>
 <head>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.9.0/p5.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.9.0//addons/p5.dom.js"></script>
 </head>
 <body>
  <div id="formula01"></div>
  <div style="width: 604px; height: 404px; background-color: #333;">
   <div id="canvas01" style="width: 600px; height: 400px; padding: 2px 2px 2px 2px;"></div>
  </div>
 <script>
/**
 * Generative formula that generates generative art?
 * 
 * @author @deconbatch
 * @version 0.1
 * p5.js 0.9.0
 * p5.dom.js 0.9.0
 * created 2019.09.12
 *
 */

// global variables
const plotMax  = 500;
const plotDiv  = 0.001;
const plotMult = 4.0;
const sizBase  = 3.0;
let hueInit    = 0.0;
let calculator = '';

function setup() {
    let canvas = createCanvas(600, 400);
    canvas.parent('canvas01');
    colorMode(HSB, 360.0, 100.0, 100.0, 100.0);
    smooth();
    noStroke();
    noLoop();

    // buttons
    const starter = createButton(' --- Run --- ');
    starter.parent('canvas01');
    starter.mousePressed(start);

    const reseter = createButton(' --- Reset --- ');
    reseter.parent('canvas01');
    reseter.mousePressed(reset);

    const stoper = createButton(' --- Stop --- ');
    stoper.parent('canvas01');
    stoper.mousePressed(stop);

    // initialize
    hueInit = random(360.0);
    reset();
}

function draw() {
    
    let hueBase = hueInit + random(90.0);
    
    xPrev = random(1.0);
    yPrev = random(1.0);
    xPlot = xPrev;
    yPlot = yPrev;
    for (plotCnt = 0; plotCnt < plotMax; plotCnt++) {
        
        let plotRatio = map(plotCnt, 0, plotMax, 0.0, 1.0);
        let pHue = hueBase + plotRatio * 30.0;
        let pSat = plotRatio * 40.0;
        let pBri = 30.0 + (1.0 - plotRatio) * 50.0;
        let pSiz = sin(PI * plotRatio) * sizBase;

        // calculate Vector Field with generated formula
        xPlot += plotDiv * cos(calculator(yPrev, xPrev) * plotMult);
        yPlot += plotDiv * sin(calculator(xPrev, yPrev) * plotMult);

        fill(pHue % 360.0, pSat, pBri, 30.0);
        ellipse(xPlot * width, yPlot * height, pSiz, pSiz);
        
        xPrev = xPlot;
        yPrev = yPlot;
    }
}

function reset() {
    // generate formula
    const parms = ['_a', '_b'];
    const oprts = [' + ', ' - ', ' * ', ' % '];
    const funcs = ['sin({p})', 'cos({p})', 'asin({p})', 'acos({p})', 'exp({p})', 'sqrt({p})', 'log({p})', 'pow({p}, 2)', 'pow({p}, -2)'];
    
    const arg01 = '_a';
    const arg02 = '_b';
    const bodyHead = 'let result = ';
    const bodyTail = '; return result;';
    const funcsCnt = floor(random(5.0, 10.0));

    //    let formula = formatByObj(funcs[floor(random(funcs.length))], { p: parms[floor(random(parms.length))] });
    let formula = funcs[floor(random(funcs.length))].replace(/\{p\}/, parms[floor(random(parms.length))]);
    for (i = 0; i < funcsCnt; i++) {
        formula += oprts[floor(random(oprts.length))];
        formula += funcs[floor(random(funcs.length))].replace(/\{p\}/, parms[floor(random(parms.length))]);
    }
    calculator = Function(arg01, arg02, bodyHead + formula + bodyTail);

    background(0.0, 0.0, 90.0, 100.0);
    document.getElementById('formula01').textContent = formula;
}

function start() {
    loop();
}

function stop() {
    noLoop();
}

 </script>

 </body>
</html>


/*
Copyright (C) 2019- deconbatch

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see 
*/




Post a Comment

0 Comments