It's a digital art animation with an abandoned strange attractor.
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!
This digital art animation is the creative coding with the '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.
The 'Processing' code example.
Please feel free to use this example code under the terms of the GPL. 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/> */