In Java, how can I write a generative formula?

Creative coding works with the generated formula.
The code that generates formula draws such generative art.

How can we...?


You can generate a function dynamically with the Function constructor in p5.js.

Generative formula that generates generative art?
I wrote a JavaScript function dynamically in this article. And you can run the code.


How about in Processing? In Java, how do we generate a function dynamically?
'Interface'? No. 'Reflection'? Maybe no.

I think I need to take it easy.
The program code in Java is only a text file. So we can cook it whatever we like!


So I thought.

Creative coding works with the generated formula.


I thought that I can write some shell script that writes Java class code as a text file.


shell script --(write formula)--> Formula.class

Then I can use that Formula.class in Vector field calculation.
A drawing class that has a Formula.class.

Draw.class ◇--- Formula.class

But I couldn't write a shell script that generates formula.
So I decided to write a Java code that generates formula and prints it to STDOUT.
And I wrote a shell script that runs Java code and redirects STDOUT to Formula.class.

And so, I made that shell script runs Draw.class after formula generation.



Implementation in Processing.

A generative art with my Processing code.


I wrote these codes in this directory structure.

run.sh
 |- Draw/
 |  |- Draw.pde
 |  |- Formula.pde
 |
 |- Generate/
    |- Generate.pde



And here are my example codes.

run.sh


#!/bin/bash

export DISPLAY=:0

pathGenerate="/home/deconbatch/somedir/Generate"
pathDraw="/home/deconbatch/somedir/Draw"
formulaClass="Formula.pde"

cd "${pathGenerate}"
ifsBackup=$IFS
IFS=$'\n'
stdout=($(/home/deconbatch/processingdir/processing-java --force --sketch=${pathGenerate}/ --run))
IFS=${ifsBackup}

echo "${stdout[0]}" > ${pathDraw}/${formulaClass}
echo "${stdout[1]}" >> ${pathDraw}/${formulaClass}
echo "${stdout[2]}" >> ${pathDraw}/${formulaClass}

cd "${pathDraw}"
/home/deconbatch/processingdir/processing-java --force --sketch=${pathDraw}/ --run "${stdout[1]}"




Formula.pde


//
// An empty file that has writable permission
//


Draw.pde


/**
 * Draw a Vector field with generated formula in Formula.pde
 * 
 * @author @deconbatch
 * @version 0.1
 * Processing 3.2.1
 * created 2019.09.20
 * 
 */

void setup() {

  size(980, 605);
  colorMode(HSB, 360, 100, 100, 100);
  smooth();
  noLoop();

}

void draw() {

  Formula fm = new Formula();
  int   lineMax = 20000;
  float plotMult = 4;
  float plotDiv  = 0.0002;
  float initHue  = random(360);

  background(0.0, 0.0, 90.0, 100.0);
  noStroke();
  for (int lineCnt = 0; lineCnt < lineMax; ++lineCnt) {
    
    float xPrev = random(0.025, 0.975);
    float yPrev = random(0.025, 0.975);
    float xCurr = xPrev;
    float yCurr = yPrev;

    float lineRatio = map(lineCnt, 0, lineMax, 0.0, 1.0);
    float baseHue   = initHue + floor(((xPrev * yPrev) * 10000.0) % 4.0) * 20.0;
    float baseSiz   = 0.5 + lineRatio;
    int   plotMax   = 200 + floor(lineRatio * 400);

    for (int plotCnt = 0; plotCnt < plotMax; ++plotCnt) {

      float plotRatio = map(plotCnt, 0, plotMax, 0.0, 1.0);

      // vector field with generated formula
      xCurr += plotDiv * cos(fm.calc(yPrev, xPrev) * plotMult);
      yCurr += plotDiv * sin(fm.calc(xPrev, yPrev) * plotMult);
      xPrev = xCurr;
      yPrev = yCurr;

      float pHue = (baseHue + plotRatio * 30.0) % 360.0;
      float pSat = map(plotRatio, 0.0, 1.0, 0.0, 50.0);
      float pBri = map(plotRatio, 0.0, 1.0, 90.0, 20.0);
      float pSiz = sin(PI * plotRatio) * baseSiz;
    
      fill(pHue, pSat, pBri, 20.0);
      ellipse(xCurr * width, yCurr * height, pSiz, pSiz);
    }    
  }

  casing();

  // write generated formula
  fill(0.0, 0.0, 0.0, 100.0);
  textAlign(CENTER);
  textSize (16);
  text(args[0], width * 0.5, height - 10.0);
  
  saveFrame("frames/####.png");
  exit();

}


/**
 * casing : draw fancy casing
 */
private void casing() {
  fill(0.0, 0.0, 0.0, 0.0);
  strokeWeight(60.0);
  stroke(0.0, 0.0, 0.0, 100.0);
  rect(0.0, 0.0, width, height);
  strokeWeight(50.0);
  stroke(0.0, 0.0, 100.0, 100.0);
  rect(0.0, 0.0, width, height);
  noStroke();
  noFill();
}



Generate.pde


/**
 * Generate formula and print it to STDOUT
 *
 * @author @deconbatch
 * @version 0.1
 * Processing 3.2.1
 * created 2019.09.20
 *
 */

void setup() {
  size(720, 720); // dummy

  // parameters
  ArrayList<string> prm = new ArrayList<string>() {
      {
        add("_a");
        add("_b");
      }
    };
  // operators
  ArrayList<string> ope = new ArrayList<string>() {
      {
        add(" + ");
        add(" - ");
        add(" * ");
        add(" % ");
      }
    };
  // Math functions
  ArrayList<string> fnc = new ArrayList<string>() {
      {
        add("sin(%s)");
        add("cos(%s)");
        add("asin(%s)");
        add("acos(%s)");
        add("atan(%s)");
        add("exp(%s)");
        add("sqrt(%s)");
        add("log(%s)");
        add("pow(%s, 2)");
        add("pow(%s, -2)");
      }
    };

  String formula = String.format(fnc.get(floor(random(fnc.size()))), prm.get(floor(random(prm.size()))));
  int fncCnt = floor(random(5, 12));
  for (int i = 0; i < fncCnt; i++) {
    formula += ope.get(floor(random(ope.size())));
    formula += String.format(fnc.get(floor(random(fnc.size()))), prm.get(floor(random(prm.size()))));
  }

  // print Java class code.
  println("public class Formula { public float calc(float _a, float _b) {return ");
  println(formula);
  println(";}}");

  exit();
  
}


/*
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 
*/








No comments :

Post a Comment