What is the abandoned strange attractors?

Strange attractors sometimes converge like this. Some creative coding that plots the strange attractors' calculation results will just draw some boring dot.


And many of them (also include me) often abandon such results and select an interesting drawing result. I feel some sense of guilt about it and feel it not fun.

I don't want to abandon the converging parameters!

So I tried to make these boring converging parameters into interesting ones.
I used De Jong attractors as strange attractors and drew the calculation results with 'vertex()'.

    frstX = sin(pA * scndY) - cos(pB * scndX);
    frstY = sin(pC * scndX) - cos(pD * scndY);

    scndX = frstX;
    scndY = frstY;

It worked and it drew interesting shapes even if I gave it the converging parameters!

Processing code examples made this image.

This digital art animation is the creative coding with 'Processing' programming language.
This code does not display any images on the screen but generates image files in frames directory. You can make an animation with these files.






'Processing' code example.

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


// Product of My Own Design.
// @deconbatch
// Processing 3.2.1
// 2018.06.24
// 10 fps x 5s animation

class deJongShape {

  float hueApply, satApply, briApply;
  float pA, pB, pC, pD;
  float frstX, scndX, thrdX;
  float frstY, scndY, thrdY;
  float multX, multY;
  
  deJongShape(float hueApply, float satApply, float briApply, float multX, float multY) {
    this.hueApply = hueApply;
    this.satApply = satApply;
    this.briApply = briApply;
    this.multX    = multX;
    this.multY    = multY;

    float seed  = 0.01;
    float scope = 100.0;
    pA = seed * floor(random(-scope, scope));
    pB = seed * floor(random(-scope, scope));
    pC = seed * floor(random(-scope, scope));
    pD = seed * floor(random(-scope, scope));

    resetShape();
   
  }

  void resetShape() {

    thrdX = sin(pA) - cos(pB);
    thrdY = sin(pC) - cos(pD);
    scndX = sin(pA * thrdY) - cos(pB * thrdX);
    scndY = sin(pC * thrdX) - cos(pD * thrdY);
    frstX = sin(pA * scndY) - cos(pB * scndX);
    frstY = sin(pC * scndX) - cos(pD * scndY);

  }

  void drawShape(float hueAdd) {

    frstX = sin(pA * scndY) - cos(pB * scndX);
    frstY = sin(pC * scndX) - cos(pD * scndY);

    stroke((hueApply + hueAdd) % 360.0, satApply, briApply, 100.0);
    fill(0.0, 0.0, 0.0, 0.0);
    beginShape(LINES);
    vertex(frstX * multX - 80.0, frstY * multY - 80.0);
    vertex(scndX * multX - 80.0, scndY * multY - 80.0);
    vertex(thrdX * multX - 80.0, thrdY * multY - 80.0);
    vertex(thrdY * multX - 80.0, thrdX * multY - 80.0);
    vertex(scndY * multX - 80.0, scndX * multY - 80.0);
    vertex(frstY * multX - 80.0, frstX * multY - 80.0);
    endShape();

    stroke(0.0, 0.0, 0.0, 0.0);
    fill((hueApply - hueAdd) % 360.0, satApply, briApply, 5.0);
    beginShape();
    vertex(frstX * multX - 80.0, frstY * multY - 80.0);
    vertex(scndX * multX - 80.0, scndY * multY - 80.0);
    vertex(scndY * multX - 80.0, scndX * multY - 80.0);
    vertex(frstY * multX - 80.0, frstX * multY - 80.0);
    endShape();

    thrdX = scndX;
    thrdY = scndY;
    scndX = frstX;
    scndY = frstY;

  }

}

void setup() {

  size(720, 720);
  colorMode(HSB, 360.0, 100.0, 100.0, 100.0);
  smooth();
  noLoop();
  strokeWeight(0.5);

}

void draw() {

  // put them just little upper
  translate(width / 2.0, height / 2.0 - 10.0);

  int   fps         = 10;
  int   frameCntMax = fps * 5;
  int   shapeCntMax = 30;
  int   drawCntMax  = 60;
  int[] drawSkip    = new int[shapeCntMax];
  float hueBase     = random(360);

  // create shape objects
  deJongShape[] djShape = new deJongShape[shapeCntMax];
  for(int shapeCnt = 0; shapeCnt < shapeCntMax; ++shapeCnt) {
    drawSkip[shapeCnt] = floor(random(5.0, 10.0));
    djShape[shapeCnt]  = new deJongShape(
                                         (hueBase + (shapeCnt % 3) * 30.0) % 360.0,
                                         map(shapeCnt % 6, 0, 5, 60.0, 80.0),
                                         map(shapeCnt % 5, 0, 4, 10.0, 50.0),
                                         width  / 6.5,
                                         height / 6.5
                                         );
  }

  // draw decomposed shape and save it for each frame
  for (int frameCnt = 0; frameCnt < frameCntMax; ++frameCnt) {
    
    background(0.0, 0.0, 90.0, 100.0);
  
    pushMatrix();
    for(int shapeCnt = 0; shapeCnt < shapeCntMax; ++shapeCnt) {

      // draw 6 shape on circle
      rotate(PI / 3.0);

      djShape[shapeCnt].resetShape();
      pushMatrix();
      for (int drawCnt = 0; drawCnt < drawCntMax; ++drawCnt) {

        // decompose
        rotate(PI * 0.005 * easeInOutCubic(map(frameCnt, 0, (frameCntMax - 1), 1.0, 0.0)));

        // draw shape
        if (drawCnt % drawSkip[shapeCnt] == 0) {
          djShape[shapeCnt].drawShape(map(drawCnt, 0, drawCntMax, 0.0, 30.0));
        }
      }
      popMatrix();

    }
    popMatrix();
    saveFrame("frames/pmod1" + String.format("%03d", frameCnt) + ".png");

  }

  // draw composed shape and save it for last part of animation
  for (int frameCnt = 0; frameCnt < fps * 1.5; ++frameCnt) {
    saveFrame("frames/pmod9" + String.format("%03d", frameCnt) + ".png");
  }

  // save composed shape for twitter thumnail
  saveFrame("frames/pmod0000.png");
  exit();

}

// easing function
float easeInOutCubic(float t) {

  t *= 2.0;
  if (t < 1.0) {
    return pow(t, 3) / 2.0;
  }
  t -= 2.0;
  return (pow(t, 3) + 2.0) / 2.0;
  
}



/*
Copyright (C) 2018- 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/>
*/