The node garden technique creates a jewel box.

Digital art of beautiful geometrical shapes.

 

Digital art of beautiful geometrical shapes.

It's a creative coding digital art animation. The code is written in the 'Processing' programming language.

When I was playing with the code using the 'node garden' technique, I found it can draw an interesting shape with lines between some nodes. And I built it into jewel box style digital art.
But I wonder a still image possibly be better than animation for this digital art?

This code does not display any images on the screen but just generates image files. You can make an animation with these files.






 

The 'Processing' code example.

Please feel free to use this examplse code under the terms of the GPL. To see other works based on my code is my pleasure. And my honor.



/**
 * Desert Rose.
 * draw desert roses in the jewel box.
 * 
 * Processing 3.2.1
 * @author @deconbatch
 * @version 0.1
 * created 0.1 2019.03.31
 */

void setup() {
  size(720, 720);
  colorMode(HSB, 360.0, 100.0, 100.0, 100.0);
  smooth();
  noLoop();
}

void draw() {

  int   frameCntMax = 24 * 6;  // for 24fps x 6sec animation
  int   colCntMax   = 4;
  float gap         = 2.0;
  float colWidth    = (width - (colCntMax + 1) * gap) * 1.0 / colCntMax;
  float hueBase     = random(360.0);
  float hueDiv      = 90.0;

  // shape parameters
  float[][] pCorner = new float[colCntMax][colCntMax];
  float[][] pJoint  = new float[colCntMax][colCntMax];
  float[][] pSoft   = new float[colCntMax][colCntMax];
  float[][] pRotate = new float[colCntMax][colCntMax];
  float[][] pHue    = new float[colCntMax][colCntMax];
  
  // make colCntMax x colCntMax cells
  background(0.0, 0.0, 60.0, 100.0);
  blendMode(BLEND);
  for (int colCnt = 0; colCnt < colCntMax; ++colCnt) {
    for (int rowCnt = 0; rowCnt < colCntMax; ++rowCnt) {
      pCorner[colCnt][rowCnt] = random(1.0);
      pJoint[colCnt][rowCnt]  = random(1.0);
      pSoft[colCnt][rowCnt]   = random(1.0);
      pRotate[colCnt][rowCnt] = random(1.0);
      pHue[colCnt][rowCnt]    = ((colCnt + rowCnt) % 3) * hueDiv * 0.25
                              + ((colCnt + rowCnt * colCntMax) * 1.0 / (colCntMax * colCntMax - 1)) * hueDiv * 0.5;
      fill((hueBase + pHue[colCnt][rowCnt] + 270.0) % 360.0, 40.0, 15.0, 100.0);
      rect(gap + (gap + colWidth) * colCnt, gap + (gap + colWidth) * rowCnt, colWidth, colWidth);
    }
  }
  noFill();

  // for drawing animation
  blendMode(SCREEN);
  for (int frameCnt = 1; frameCnt < frameCntMax; ++frameCnt) {

    float frameRatio = map(frameCnt, 1, frameCntMax, 0.0, 1.0);

    for (int colCnt = 0; colCnt < colCntMax; ++colCnt) {
      for (int rowCnt = 0; rowCnt < colCntMax; ++rowCnt) {
      
        float roseX       = gap + colWidth * 0.5 + (gap + colWidth) * colCnt;
        float roseY       = gap + colWidth * 0.5 + (gap + colWidth) * rowCnt;
        int   roseCorners = floor(map(pCorner[colCnt][rowCnt], 0.0, 1.0, 2.5, 7.5));
        int   roseJoints  = floor(map(pJoint[colCnt][rowCnt], 0.0, 1.0, 2.0, 6.0));
        float roseSize    = colWidth * map(pJoint[colCnt][rowCnt], 0.0, 1.0, 0.6, 0.4);
        float roseSoft    = map(pSoft[colCnt][rowCnt], 0.0, 1.0, 0.02, 0.15);
        float roseHue     = hueBase + pHue[colCnt][rowCnt];
    
        pushMatrix();
        translate(roseX, roseY);
        rotate(HALF_PI * pRotate[colCnt][rowCnt]);
        drawRose(roseCorners, roseJoints, roseSize, roseSoft, roseHue, frameRatio);
        popMatrix();
    
      }
    }
    saveFrame("frames/" + String.format("%04d", frameCnt) + ".png");
  }

  // make 24fps x 1sec no moving images
  for (int frameCnt = frameCntMax; frameCnt < frameCntMax + 24 * 1.5; ++frameCnt) {
    saveFrame("frames/" + String.format("%04d", frameCnt) + ".png");
  }

  // make twitter thumbnail image
  saveFrame("frames/0000.png");
  exit();

}

/**
 * drawRose : draw rose image.
 * @param  _corners   : corner count of rose.
 * @param  _joints    : joint count of rose.
 * @param  _roseSize  : size of rose.
 * @param  _softness  : 0.02 - 0.2 : shape softness.
 * @param  _hueBase   : hue value of rose.
 * @param  _drawRatio : 0.0 - 1.0 : drawing ratio of the total.
 * too many parameters!
 */
private void drawRose(int _corners, int _joints, float _roseSize, float _softness, float _hueBase, float _drawRatio) {

  // make node list
  NodeList[] jointNodes = new NodeList[_joints];
  for (int jointCnt = 0; jointCnt < _joints; ++jointCnt) {

    float jointRatio = map(jointCnt, 0, _joints, 0.0, 1.0);
    jointNodes[jointCnt] = new NodeList();

    for (int cornerCnt = 0; cornerCnt < _corners; ++cornerCnt) {

      float cornerRatio = map(cornerCnt, 0, _corners, 0.0, 1.0);
      float shapeFactor = sin(TWO_PI * (cornerRatio + _drawRatio));

      float centerSize = noise(_hueBase * _corners + _joints) * 0.6;  // random center hole size
      float direction  = noise(_hueBase * _joints + _corners) < 0.5 ? 1.0 : -1.0; // random rotate direction
      float nRadius = _roseSize * (centerSize + (1.0 - centerSize) * jointRatio);
      float nRadian = direction * TWO_PI * (cornerRatio + map(shapeFactor, -1.0, 1.0, -_softness, _softness));

      float nX = nRadius * cos(nRadian);
      float nY = nRadius * sin(nRadian);
    
      Node joint = new Node(new PVector(nX, nY));
      jointNodes[jointCnt].add(joint);

    }
  }

  // draw lines with node lists
  for (int jointCnt = 0; jointCnt < _joints - 1; ++jointCnt) {
    float jointRatio = map(jointCnt, 0, _joints - 1, 0.0, 1.0);
    jointNodes[jointCnt].drawLines(jointNodes[jointCnt + 1], _hueBase, jointRatio, 5.0 / (_corners + _joints));
  }
  
}

/**
 * Keep node information.
 * @param  _position : node position
 */
class Node {
  PVector position;
  Node(PVector _position) {
    position = new PVector();
    position.set(_position);
  }
}

/**
 * Keep nodes in one joint.
 * number of nodes = number of corners.
 * draw lines from some joint to other joint.
 * @param  _otherNodes : draw lines to this nodes.
 * @param  _hueBase    : hue value of lines.
 * @param  _jointRatio : 0.0 - 1.0 : joint ratio of the total. from center to outer.
 * @param  _density    : 0.0 - 1.0 : to control stroke weight. bigger = thick.
 */
import java.util.Iterator;
class NodeList extends ArrayList<Node> {
  void drawLines(NodeList _otherNodes, float _hueBase, float _jointRatio, float _density) {

    Iterator<Node> itNode = this.iterator();
    Iterator<Node> itOther = _otherNodes.iterator();

    strokeWeight(0.2 + _jointRatio * map(_density, 0.0, 1.0, 0.0, 1.2));
    stroke(
           (_hueBase + map(_jointRatio, 0.0, 1.0, -15.0, 15.0)) % 360.0,
           60.0 - 20.0 * _jointRatio,
           50.0 - 20.0 * _jointRatio,
           100.0
           );

    beginShape();
    while (itNode.hasNext()) {
      Node node = itNode.next();
      vertex(node.position.x, node.position.y);
      if ((itOther.hasNext())) {
        Node other = itOther.next();
        vertex(other.position.x, other.position.y);
      }
    }
    endShape(CLOSE);
  }
}


/*
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 <http://www.gnu.org/licenses/>
*/



 

Next Post Previous Post
No Comment
Add Comment
comment url