Mathematical Morphogenesis: De Jong Attractors on Polar Coordinates

A creative coding that draws De Jong attractors on polar coordinates.

 

A Unique Approach to De Jong Attractors

This generative artwork was created using Processing.

I wanted to explore the visual possibilities of mapping De Jong attractors onto polar coordinates. While there are many ways to implement polar transformations, I opted for the following approach:




    // De Jong Attractor formula
    float currX = sin(TWO_PI * djA * prevY) - cos(TWO_PI * djB * prevX);
    float currY = sin(TWO_PI * djC * prevX) - cos(TWO_PI * djD * prevY);

    // Mapping to polar coordinates
    float dX = width  * 0.15 * currX;
    float dY = height * 0.15 * currX;
    float dR = rBase * currY;
    float px = dX * cos(dR) - dY * sin(dR);
    float py = dY * cos(dR) + dX * sin(dR);


 

Managing Convergence

There is a convergence problem in drawing attractors. I tried to avoid this by changing the attractor parameter in recurrence.




    // Re-randomizing to prevent convergence (triggered at 60% of max points)
    if (pCnt == floor(pMax * 0.6)){
      djA = random(-1.0, 1.0);
      djB = 1.0;
      djC = random(-1.0, 1.0);
      djD = 1.0;
    }


 

Visual Variations

1. The "Ball" Formation

    float px = width  * sin(_x * _y) * cos(_r * _x);
    float py = height * cos(_x * _y) * sin(_r * _y);
A generative art with De Jong attractor. It looks like a ball shape.

 

2. The "Square" Formation

    float px = width  * sin(_x) * cos(PI * _x);
    float py = height * cos(_y) * sin(PI * _y);

A generative art with De Jong attractor. It a square shape.

 

3. The "Cloth" Texture

    float px = width  * sin(_y) * cos(PI * _x);
    float py = height * cos(_x) * sin(PI * _y);

A generative art with De Jong attractor. It looks like a cloth.







 

The Processing Example Code

This code is designed for offline rendering; it saves high-quality frames directly to your /frames directory rather than rendering to the screen in real-time.

This code is released under the GPL license. Please feel free to experiment with it—I’m always honored and excited to see new works inspired by my implementations.



/**
 * Just Another Nervous Wreck.
 * 
 * A creative coding that draws De Jong attractors on polar coordinates.
 * 
 * Processing 3.5.3
 * @author @deconbatch
 * @version 0.1
 * created 0.1 2020.01.26
 */

void setup() {

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

}

void draw() {

  int   frmMax  = 3;
  float hueBase = random(360);

  translate(width / 2, height / 2);
  for (int frmCnt = 0; frmCnt < frmMax; frmCnt++) {

    blendMode(DIFFERENCE);
    background(0.0, 0.0, 90.0, 100.0);
    hueBase += 90.0;

    pushMatrix();
    rotate(random(PI));
    drawWreck(hueBase);
    popMatrix();  
    
    blendMode(BLEND);
    casing(hueBase);
    
    saveFrame("frames/" + String.format("%04d", frmCnt + 1) + ".png");
  }
  exit();
}

/**
 * drawWreck : draws De Jong attractors on polar coordinates
 * @param  _hueBase : drawing color.
 */
void drawWreck(float _hueBase) {

  float hueBase = _hueBase;

  // De Jong Attractor parameters
  float djA   = 1.0;
  float djB   = random(-1.0, 1.0);
  float djC   = 1.0;
  float djD   = random(-1.0, 1.0);
  float prevX = random(-2.0, 2.0);
  float prevY = random(-2.0, 2.0);

  float rBase = random(0.2, 0.5) * HALF_PI;
  float sBase = 0.25;
  int   pMax  = 12000000;

  noStroke();
  for (int pCnt = 0; pCnt < pMax; pCnt++) {

    // for avoid convergence (as much as possible)
    if (pCnt == floor(pMax * 0.6)){
      djA = random(-1.0, 1.0);
      djB = 1.0;
      djC = random(-1.0, 1.0);
      djD = 1.0;
      hueBase += 30.0;
    }

    // De Jong Attractors
    float currX = sin(TWO_PI * djA * prevY) - cos(TWO_PI * djB * prevX);
    float currY = sin(TWO_PI * djC * prevX) - cos(TWO_PI * djD * prevY);

    // polar coordinates
    float dX = width  * 0.15 * currX;
    float dY = height * 0.15 * currX;
    float dR = rBase * currY;
    float px = dX * cos(dR) - dY * sin(dR);
    float py = dY * cos(dR) + dX * sin(dR);
    float ps = sBase * (1.0 + dist(px, py, 0.0, 0.0) * 2.0 / width);

    fill(hueBase % 360.0, 40.0, 15.0, 100.0);
    ellipse(px, py, ps, ps);

    prevX = currX;
    prevY = currY;

  }
}


/**
 * casing : draw fancy casing
 * @param  _hueBase : casing color.
 */
private void casing(float _hueBase) {
  
  fill(0.0, 0.0, 0.0, 0.0);
  strokeWeight(40.0);
  stroke(_hueBase, 60.0, 20.0, 100.0);
  rect(0.0, 0.0, width, height);
  strokeWeight(30.0);
  stroke(0.0, 0.0, 95.0, 100.0);
  rect(0.0, 0.0, width, height);
    
}

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



 

Gallery: Further Examples

Here are a few more outputs generated with this specific algorithm.


A creative coding that draws De Jong attractors on polar coordinates.

A creative coding that draws De Jong attractors on polar coordinates.

A creative coding that draws De Jong attractors on polar coordinates.

 

Next Post Previous Post
No Comment
Add Comment
comment url