The saga of the round square and the square circle

I’m almost too bored to write about these experiments, but I know I need to keep a record as I will definitely forget all the steps and thought processes. I’m not going to go into all of the ins and outs here and will write more about the noise variations separately later. This post is just to record how to make the square circle shape.

To start with I picked this circle square shape because I liked the challenge of the irregularity of it, but the possibility of building it with simple blocks. I also liked the idea that I could get a large amount of variation through actually something that was really just 2 options. By which I mean there are 4 ‘corners’ to this shape and each corner can either be a right angle or an arc. I think that creates 1 + 4 + 4 + 2 + 4 + 1 = 16 permutations/orientations[1]. Without taking into account rotation/orientation there are 1 + 1 + 2 + 1 + 1 = 6 possible shapes[2].

I am sure this also lends itself to an array, but I felt I needed to be more explicit about the vertices and shapes to keep track of what I was doing. My first attempt by trying to avoid complicated code and just using rect() and ellipse() actually ended up being more complicated that it needed to be but it made me thing about a few things. I knew I needed to ‘anchor’ each shape by the coordinates of the centre and that this centre point could be defined in a grid formation. So that meant initialising the centre point and then determining everything else from that centre point. I also knew that I couldn’t use stroke() to draw a line around the shape because I would get cross-hairs in the middle. So instead I needed to draw two of the same shape on top of each other one slightly larger than the other so that it formed a layer around. All of these with a solid fill.

In words, I started with the larger shape made up of 4 quarters, each of which could either be a square of height and width = d2, or a quarter circle of radius d2. Then draw the same, but with slightly smaller height and width = d1. But when I tried a few options, I realised there were still some overlap issues, so what I did was, for each quarter, draw either a square or no square, and then on top draw full circle. So for one shape the code is below where d2 has been defined earlier and the random case changes are defined as variables as they are used again to produce the second slightly smaller version.

  // generate a switch case on or off for each quarter
  int shapeCase1 = (int) random (2);
  int shapeCase2 = (int) random (2);
  int shapeCase3 = (int) random (2);
  int shapeCase4 = (int) random (2);

  // Quarter 1 outside
  fill(largeSh); // colour for outer shape forming the outline
  if (shapeCase1 == 0){ //draw rectangle
  rect(xPos, yPos, d2, d2);
  // Quarter 2 outside
  if (shapeCase2 == 0){ //draw rectangle
  rect(xPos-d2, yPos, d2, d2);
  // Quarter 3 outside
  if (shapeCase3 == 0){ //draw rectangle  
  rect(xPos-d2, yPos-d2, d2, d2);
  // Quarter 4 outside  
  if (shapeCase4 == 0){ //draw rectangle
  rect(xPos, yPos-d2, d2, d2);
  ellipse(xPos, yPos, 2*d2, 2*d2); // fills in the rest of the shape with circle


That method worked adequately for the experiments with colour that I wrote about in the previous post. However this method was not going to work if what I wanted to do was have transparent layers and multiple lines drawn with some noise to make it look sketchy. Which is what I was wanting to do next. So I had to go back and work out how to draw the shape as one object. That meant looking at how to draw curves and use the beginShape() and endShape() functions. I also thought at this stage it would make sense to pull out the code for the object being created into a function and then I could use that function elsewhere.


First I defined a set of x and y coordinates for the vertex() and bezierVertex() and the control points for the Bezier curves. I will come back to the defining of these coordinates further below. First, this is the code for the shape. The variables ranQ1, ranQ2, ranQ3, ranQ4 and ranTest are defined earlier, so that I can change the amount of variation (eg a greater proportion of one shape over another) in one go if I want to by adjusting the variables.

        beginShape(); // SHAPE STARTS HERE
          fill (shapeCol); // fill colour defined at top
          stroke(shapeLine); //line colour defined at top
          vertex(xB1, yB1); //first point
          // *********** Q1**************
          if (ranQ1<ranTest){
          bezierVertex(xC1, yC1, xC2, yC2, xB3, yB3); // Q1 curve
          } else {// Q1 corner
          //************ Q2 *************
          bezierVertex(xC3, yC3, xC4, yC4, xB5, yB5); // Q2 curve
          } else {// Q2 corner
          //************ Q3 *************
          if (ranQ3<ranTest){
          bezierVertex(xC5, yC5, xC6, yC6, xB7, yB7); // Q3 curve
          } else {// Q3 corner
           vertex(xB6, yB6);
           vertex(xB7, yB7);
          //************ Q4 *************
          if (ranQ4<ranTest){
          bezierVertex(xC7, yC7, xC8, yC8, xB1, yB1); // Q4 curve
          } else { // Q4 corner
Diagram showing point labelling

Diagram showing point labelling

This is the code for the grid points. The centre is (xA, yA). Then there are 8 points around that (xB1, yB1)… (xB8, yB8), which form the corners and midpoints of a square. Then there are the 8 Bezier control points (xC1, yC1)… (xC8, yC8) to form the arc for each quarter. I didn’t know what position these needed to be, so I just played around until I got something close using a scatter approach and then refining. I’m sure there is a mathematical formula relationship but how to find it? The factor is a near enough approximation. d is the width and height of each quarter square or the radius of the circle. dx and dy are the distances to the bezier curve control points as shown in the diagram.

   // set values of x and y for points
   xB1 = xA + d;
   yB1 = yA;
   xB2= xB1;
   yB2 = yB1 + d;
   xB3 = xB2 - d;
   yB3 = yB2;
   xB4 = xB3 - d;
   yB4 = yB3;
   xB5 = xB4;
   yB5 = yB4 - d;
   xB6 = xB5;
   yB6 = yB5 - d;
   xB7 = xB6 + d;
   yB7 = yB6;
   xB8 = xB7 + d;
   yB8 = yB7;

        // ************BEZIERVERTEX VALUES ********
        // define bezier points to draw a curve
        float dx = 0.575*d;// nearest value to a circle 
        float dy = 0.575*d;// by trial and error
        xC1 = xB1;
        yC1 = yB1 + dy;
        xC2 = xB3 + dx;
        yC2 = yB3;
        xC3 = xB3 - dx;
        yC3 = yB3;
        xC4 = xB5;
        yC4 = yB5 +dy;
        xC5 = xB5;
        yC5 = yB5 - dy;
        xC6 = xB7 - dx;
        yC6 = yB7;
        xC7 = xB7 + dx;
        yC7 = yB7;
        xC8 = xB1;
        yC8 = yB1 - dy;


[1] 1xall square, 4x(one round three square), 4x(two round two square together), 2x(two round two square opposite diagonals), 4x(three rounds one square), 1x all round.

[2] 1xall square, 1x(one round three square), 2x(two round two square), 1x(three rounds one square), 1x all round


702 Total Views 1 Views Today

You may also like...

Leave a Reply