The Artist's Husband: Entanglement

· Read in about 6 min · (1078 words) ·

In my last two posts, I showed how to draw most of the Aah tangle using the Javascript p5.js library. In this post, the Aah is complete, as you can see from the image below. However, the Javascript code to do so, does not follow directly from what we saw in those previous posts. I have rewritten it and packaged it into a library: Entanglement. More about that shortly.

First, lets talk about how the Aah pattern was completed. You’ll recall that we had successfully generated the 8-armed starburst pattern, and distributed copies of it the around the canvas, with some random variations to make it seem more like it was hand-drawn. We avoided overlapping them by using collision detection: we draw a polygon around each pattern, and then as we create new ones, we check the polygon against those for the patterns we had already drawn to make sure there were no collisions. The final image we generated was nice, but missing something important: an Aah tangle is supposed to have small circles randomly scattered between the starburst patterns.

Generating the circles was easy. We are already set up to do collision detection, so there were just a few steps necessary.

  • Generate a circle
  • Draw a polygon around it (how big we make the polygon affects the spacing of the circles)
  • Compare the polygon to all the other polygons for items we have drawn on the canvas, including all the starbursts and other circles
  • If no conflict, draw the circle
  • Repeat until we have enough circles

How do we know we have enough circles? Just try to draw way more than will actually fit – they will tend to fill in fairly evenly between the other patterns around the canvas.

As I was trying to add this to the Javascript code we had before, it became quite unwieldy and hard to read. So I reorganized it all into the beginnings of a general purpose library for drawing Zentangles.

Entanglement

Enganglement is an experiment to see if I can write a general purpose library to assist in the programmatic drawing of Zentangles. It is very different from the code we looked at in other posts, although it does the same thing with more configurable options. I am not going to print it out in this post, as it’s a bit long. Those of you interested in looking at it can find it on GitHub.

Right now, Entanglement doesn’t do much that we haven’t seen up until now – you can use it to generate an image of an AAH tangle. I hope to add more tangles and tangle elements in the future, and provide ways to combine them into pleasing images.

You don’t have to read and understand the code in the library to make use of it! You can just use it like any other library. You will want to read the documentation as it has an explanation of all the options and several examples. This post will provide a few more.

Getting Started

To use Entanglement, you need to load it and its dependencies. It relies on the p5.js library, and the p5.collide2D library. You can load all three by adding this to your HTML file:

<script src="https://cdn.jsdelivr.net/npm/p5@1.0.0/lib/p5.js"></script>
<script src="https://cdn.jsdelivr.net/gh/bmoren/p5.collide2d/p5.collide2d.min.js"></script>
<script src="https://cdn.jsdelivr.net/gh/tektsu/entanglement/dist/entanglement.js"></script>

Then it’s just a matter of calling classes and methods in the library and have it do your bidding!

Examples

To draw a traditional AAH tangle, you don’t need many options; the defaults will do. Here is the code:

const height = 600;
const width = 600;

function setup() {
    createCanvas(width, height);
    background(240);
}

function draw() {
    let aahs = new Aahs(Box.newFromXY(0, 0, width, height), {});
    aahs.draw();
    noLoop();
}

That will generate an image much like the one above.

In p5.js, you can set a color used to draw a line (stroke) and the color used to fill in a shape (fill). The Entanglement Aahs class lets you set these separately for the dots and the starbursts. Note that the dots on the end of the starburst arms are circle shapes that get a fill color. In this example, we’ll also make the dots bigger and let them be closer together. We’ll also set the background to pure white.

const height = 600;
const width = 600;

function setup() {
    createCanvas(width, height);
    background(255);
}

function draw() {
    let aahs = new Aahs(Box.newFromXY(0, 0, width, height), {
        plan: {
            dot: {
                size: new Range(4, 10),
                spacing: 100,
                fillColor: color(255,0,0),
                strokeColor: color(128,0,0),
            },
            aah: {
                fillColor: color(0,0,255),
                strokeColor: color(0,0,128),
            }
        },
    });
    aahs.draw();
    noLoop();
}

You can put some fairly extreme values in for some of the options and come up with something that does not look like AAH at all! Here we set the background to black, and only draw one large yellow starburst with 1000 arms, surrounded by white dots. It looks a bit like an explosion in outer space…

const height = 600;
const width = 600;

function setup() {
    createCanvas(width, height);
    background(0);
}

function draw() {
    let aahs = new Aahs(Box.newFromXY(0, 0, width, height), {
        margin: 0,
        plan: {
            dot: {
                spacing: 200,
                fillColor: color(255,255,255),
                strokeColor: color(255,255,255),
            },
            aah: {
                size: 300,
                desiredCount: 1,
                armCount: 1000,
                fillColor: color(255,255,0),
                strokeColor: color(200,200,0),
            }
        },
    });
    aahs.draw();
    noLoop();
}

You don’t have to let the Aahs class place the components randomly for you. Here we use the Aahs class to fill the canvas with white dots, then draw a series of starburst patterns (Aah class) over it in a grid. For each of these, rotation is turned off, and are arm angle variation (theta) is kept to a minimum.

const height = 600;
const width = 600;

function setup() {
    createCanvas(width, height);
    background(170, 170, 200);
}

function draw() {
    let aahs = new Aahs(Box.newFromXY(0, 0, width, height), {
        margin: 0,
        plan: {
            dot: {
                spacing: 100,
                size: 6,
                fillColor: 'white',
                strokeColor: color(0, 0, 0),
            },
            aah: {
                enable: false,
            }
        },
    });
    aahs.draw();
    for (let x=0; x<=width; x+=100) {
      for (let y=0; y<=height; y+=100) {
        const aah = new Aah(75, new Point(x, y), {
          rotate: false,
          thetaSD: 1,
        });
        aah.draw();
      }
    }
  
  noLoop();
}

As you can see, you can get quite a bit of variation by changing the options. Feel free to play with them to see what happens! As I mentioned, Entanglement is an experiment and is in its very early stages. It’s likely to change quite a bit (hopefully for the better) as it grows. I’m curious to see where it leads!