-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 After going through a bit of history on using computers to make art, my second class on p5.js had us attempt to be inspired by geometric artwork and write code to make something cool. In about an hour and a half of coding, I ended up with this — randomly generated triangles in all kinds of colors. ![image1] We were tasked to continue working on it until we were happy with it — play around with shape, size and color. I spun some things around in my head during a long commute — **I’m determined to get all these triangles to be all connected and not overlap**. It was something we discussed before starting the project but we deemed it too difficult to do consider we’re only 3 hours into learning p5. We looked at a library that accomplished it, but I needed to come up with my own solution. I have a difficult time drawing while I’m driving so as soon as I managed to stop I sketched this out: ![image2] What if, instead of Random coordinates to create the triangles, I could - - setup a grid on the canvas - - randomly place the points in that grid - - store the coordinates in an array - - then manage to systematically go through and start using those points to create the new triangles In my head it seems like it could work — getting rid of the randomness of the triangle generation. **Let’s see how far I get into this code before I realize how dumb I was to think this would work.** ## Setting up the grid Just so I can see what my brain is thinking, I’m physically putting the grid onto the canvas: {{< highlight javascript >}} function setup() { createCanvas( windowWidth, windowHeight ) colorMode( HSB ) noLoop() noStroke() } function draw() { background( 20, 20, 20) // Setup a grid so i can figure out the uppper and lower bounds // of where the points should go var columns = 5 var rows = 5 var columnWidth = ( windowWidth / columns ) var columnHeight = ( windowHeight / rows ) fill( 30, 30, 30) stroke( 90, 90, 90 ) rect( 0, 0, columnWidth, columnHeight ) // Create a row for ( i = 0; i < rows; i++ ){ // Create a column for ( j = 0; j < columns; j++ ){ rect( j * columnWidth, i * columnHeight, columnWidth, columnHeight ) } } } {{< /highlight >}} Which ended up looking like this. I’m off to an okay start. ![image3] ## Generating the random points I’m going to generate random points inside each grid using the upper and lower bounds based on the column width and height and use small circles to visualize where the points are being created. So just in side the column loop: {{< highlight javascript >}} for ( j = 0; j < columns + 1 ; j++ ){ rect( j * columnWidth, i * columnHeight, columnWidth, columnHeight ) //create my point var pointPositionX = random( j * columnWidth - columnWidth, j * columnWidth ) var pointPositionY = random( i * columnHeight - columnHeight, i * columnHeight ) circle( pointPositionX, pointPositionY, 10 ) } {{< /highlight >}} and I get some points: ![image4] ## Storing the coordinates in arrays I need to keep all these coordinates so that I can go back and create the triangles. {{< highlight javascript >}} for ( i = 0; i < rows + 1; i++ ){ var columnData = [] // Create a column for ( j = 0; j < columns + 1 ; j++ ){ rect( j * columnWidth, i * columnHeight, columnWidth, columnHeight ) //create my point var pointPositionX = random( j * columnWidth - columnWidth, j * columnWidth ) var pointPositionY = random( i * columnHeight - columnHeight, i * columnHeight ) columnData.push( [pointPositionX, pointPositionY] ) console.log( columnData ) //circle( pointPositionX, pointPositionY, 10 ) } allCoordinates.push( columnData ) console.log( allCoordinates ) } {{< /highlight >}} It has been a few years since I’ve written some JavaScript but it’s seeming to fit like a glove. This is what was logged to the console. **I think I somehow managed to do this nearly right*** … except those negative numbers … ![image5] ## The first triangle Yeah, so those negative numbers weren’t great. Math is weird sometimes for me — why would I be subtracting from 0? Who knows. I think I thought that i and j were 1's? Whatever. Fixed it. Also don’t know why I needed two arrays…I should just push all the coordinates to ```allCoordinates[]```. So once all that was out the way, I wanted to make sure those first points were stored as I expected them and that I could make a triangle from them. This is what the code ended up being: {{< highlight javascript >}} var allCoordinates = []; // Create a row for ( i = 0; i < rows + 1; i++ ){ // Create a column for ( j = 0; j < columns + 1 ; j++ ){ rect( j * columnWidth, i * columnHeight, columnWidth, columnHeight ) //create my point var pointPositionX = random( j * columnWidth + columnWidth, j * columnWidth ) var pointPositionY = random( i * columnHeight + columnHeight, i * columnHeight ) allCoordinates.push( [pointPositionX, pointPositionY] ) circle( pointPositionX, pointPositionY, 10 ) console.log(allCoordinates) } } // Create the first triangle fill( 90, 90, 90 ) var currentPoint = 0 var firstPointX = allCoordinates[0][0] var firstPointY = allCoordinates[0][1] var secondPointX = allCoordinates[1][0] var secondPointY = allCoordinates[1][1] var thirdPointX = allCoordinates[6][0] var thirdPointY = allCoordinates[6][1] triangle( firstPointX, firstPointY, secondPointX, secondPointY, thirdPointX, thirdPointY ) {{< /highlight >}} and the output: ![image7] **Fantastic!** Now I gotta loop through and do them all! ## 2 hours of crashing my browser later… I spent a good bit of time working out how to cycle through each of the points in the array and creating 2 triangles for every point. I messed it up a lot given that I also had to figure out if it was in the first or last row or the last column — it was weird. I finally got to a point where I was okay with the output and knew that if I just spent another hour on it I could have gotten in nearly perfect…but I was ready to just move on — **I’m not trying to overachieve this**. I won’t share that code with you, but here’s how it was shaping up: ![image8] ## Back to the Art part of this whole thing With some adjustments of the number of columns and rows, some creative cropping and some actual color choices I came up with a couple iterations before finally enjoying where it was headed. Getting closer… ![image9] ## The final render and some pretty sloppy code Finally, the renders started coming together to a better point — enough where I could say that I was done for now. This is the final render: ![image10] And the p5.js code. Sorry, I was ready to call it done today so there’s no cleaning it up. Enjoy it. {{< highlight javascript >}} function setup() { var canvas = createCanvas( 1600, 1600 ) canvas.parent("canvasArea"); colorMode( HSB ) noLoop() noStroke() } function draw() { background( 197, 31, 65 ) // Setup a grid so i can figure out the uppper and lower bounds // of where the points should go var columns = 20 var rows = 20 var columnWidth = 1600 / columns var columnHeight = 1600 / rows // Show the grid fill( 18, 11, 18 ) //stroke( 90, 90, 90 ) //rect( 0, 0, columnWidth, columnHeight ) var allCoordinates = []; // Create a row for ( i = 0; i < rows; i++ ){ // Create a column for ( j = 0; j < columns ; j++ ){ rect( j * columnWidth, i * columnHeight, columnWidth, columnHeight ) //create my point var pointPositionX = random( j * columnWidth + columnWidth, j * columnWidth ) var pointPositionY = random( i * columnHeight + columnHeight, i * columnHeight ) allCoordinates.push( [pointPositionX, pointPositionY] ) circle( pointPositionX, pointPositionY, 10 ) } } var whichRow = 1 var l = 1 while ( l < allCoordinates.length ){ //firstTriangle if (whichRow == 1 || whichRow == rows){ //don't do anything on the first and last row (thse need just one triangle) } else{ if ( (l + 1) % rows == 0 || l == 0){ console.log("it's the last item, do nothing") } else{ //Triangle 1 var colorChoices = [ [45, 15, 75], [22, 42, 95], [5, 55, 75], [0, 61, 95] ] var randomColorChoice = Math.floor(random(0,4)) fill( colorChoices[randomColorChoice][0], colorChoices[randomColorChoice][1], Math.floor(random(50,100)) ) //stroke( 200, 90, 90 ) var currentPoint = l var nextPoint = l + 1 var bottomPoint = l + rows var firstPointX = allCoordinates[currentPoint][0] var firstPointY = allCoordinates[currentPoint][1] var secondPointX = allCoordinates[nextPoint][0] var secondPointY = allCoordinates[nextPoint][1] var thirdPointX = allCoordinates[bottomPoint][0] var thirdPointY = allCoordinates[bottomPoint][1] triangle(firstPointX, firstPointY, secondPointX, secondPointY, thirdPointX, thirdPointY) //Triangle 2 randomColorChoice = Math.floor(random(0,4)) fill( colorChoices[randomColorChoice][0], colorChoices[randomColorChoice][1], Math.floor(random(50,100)) ) //stroke( 200, 90, 90 ) var currentPoint = l var nextPoint = l - rows var bottomPoint = l + 1 var firstPointX = allCoordinates[currentPoint][0] var firstPointY = allCoordinates[currentPoint][1] var secondPointX = allCoordinates[nextPoint][0] var secondPointY = allCoordinates[nextPoint][1] var thirdPointX = allCoordinates[bottomPoint][0] var thirdPointY = allCoordinates[bottomPoint][1] triangle( firstPointX, firstPointY, secondPointX, secondPointY, thirdPointX, thirdPointY ) } } l++ if ( l % rows == 0 ){ whichRow++ } } } {{< /highlight >}} ## Working demo Check out the [working demo](/p5/generative-art-pattern-triangles/index.html). [image1]: /support/generative-art-triangles/random-triangles.png "Random Triangles" [image2]: /support/generative-art-triangles/sketch-triangles.jpg "Rough sketch of my approach" [image3]: /support/generative-art-triangles/grid.png "Baseline Grid" [image4]: /support/generative-art-triangles/grid-with-circles.png "Visualizing the coordinates" [image5]: /support/generative-art-triangles/arrays.png "Those numbers almost seem like they’re right" [image6]: /support/generative-art-triangles/first-triangle.png "Hey, the first triangle is in the right spot!" [image7]: /support/generative-art-triangles/first-triangle.png "Hey, the first triangle is in the right spot!" [image8]: /support/generative-art-triangles/lots-of-colored-triangles.png "Yeah, there are missing triangles, I just couldn’t bring myself to fix them right now." [image9]: /support/generative-art-triangles/Final-Render-1.png "Getting closer to a render that I’m liking" [image10]: /support/generative-art-triangles/Final-Render-2.png "The last render I did before I called it quits. I think I like it!" -----BEGIN PGP SIGNATURE----- iQIcBAEBAgAGBQJc8diWAAoJELuvSL2hxBDYFcAP/iHL7MW0Vcoi+Aa0J5vOvPPO Xgf0y96592dFRBC3MyByS+2b0YOzhbXKeoa8OVKcyTVjXmD9fh6P+JXXaniTACrd p+hZOc4uAOVKy4rw6RnJhl6zrgGCXpWlFTpAhKrCdCS+WK7GYX9scaB8hLO/oKW/ xn9rsaDl2KsUMykYMp5H5pz76RN77laUu1bi5Ud9+L0uF848OqYQJR4+du9uJWUN tayst37mjD5zM46f3To7fURC+QbfYRxc7a9QEjo5wRGpQYnzN39YG8+8ZV/AFjIH gqrJWeWFRDh2tSRX4Kf17vHnl9mRCKdUC2CXOpsCvJ6TUfxHdqkatCy+ejMKJW8I qCjPbfNc9FvwNPyCUXIJ3vTRL0+BVpqrls38qwn8Q4pp1jgHRcY5uVDXRCTsODbE IX9grXVfGy2JaYt+zizCtNqeuxu9XxvvAbDRnp8pwrotaTRSSm9dsnT5cktV/O5z qyBD9ohcbiifF3LM/GT+YIqzqP/7UEdB+uRfjT3RBZKY1TZmRCVIA+tBdUt0nxMc gj2cTiq+pTccXtLctF6tPlv8hv0y6h464xExhTVLamoPaOM8c/dm6sLhCsfMbtT2 HK3gLfa6F82jvbZm4Wr1abhAmCWKyTDNXTq9IUx0tUwrxJeDiKgmQAy9ozBog8BF Hw+Pf0IlwZQYWYi27IQu =FwpB -----END PGP SIGNATURE-----