More from Blog - Amy Goodchild
There’s some fun computational geometry in my latest artwork, and in this article I’ll walk through how I take a scramble of disconnected paths and turn them into closed shapes, using half-edges and a planar graph. Work in progress output Work in progress output Work in progress output Agent paths These images begin with a set of “agents” that draw paths. You can think of an agent as a dot that does things (it has “behaviours”). These agents: move around the canvas, leaving a trail behind check whether they’ve run into any existing trails (their own or another agent’s) when they first run into a trail, they go back to the beginning of their journey and move in the opposite direction. when the second end hits something, the path is complete and a new agent is generated somewhere else. Here’s an example with just one agent at a time. The smooth motion of the agents is controlled using Perlin noise, which is essentially a grid of random numbers. To figure out their next move, each agent looks up the number at their current position and uses it to decide which direction to go in next. For example, if the number is 0 they move at an angle of 0°, if the number is 0.25 they move at 90°, 0.5 at 180°, etc. If the values in the field were completely random, the agents would jitter back and forth, constantly changing direction wildly. With Perlin noise, numbers that are close to each other in the grid are similar, so the direction only changes a little bit every step, creating a smooth wandering line. In this animation I’ve drawn a grid of arrows to depict the noise field and you can see the agent following their directions. (As an agent does the second half of its path, it goes backwards along the arrows). After the agents have been drawing paths for a while, the canvas looks something this. Agent paths Right now, what we have is a collection of disconnected paths, one drawn by each agent. They are touching but as far as the computer is concerned, they aren’t connected and these aren’t closed shapes. That means we need to do some work to be able to fill them with colour. There are lots of approaches for this. Some involve drawing the paths out and then looking at the colours of the individual pixels to know if we’re looking at a path or an empty space. You would pick a starting pixel, change it to a fill colour and then move in lines or spreading outwards until you hit pixels that are already filled with the path colour. I had started implementing that a while ago and had a bug that created these super glitchy images, which I love, even though they weren’t what I had planned. Glitchy shape filler Glitchy shape filler For this new project, I wanted to try joining the disconnected edges into fully closed shapes. Luckily there is an established method for this, a planar graph, so I just had to figure it out. Vibe coding? More like vibe front-loading Full disclosure, I had no idea how to do this when I started. I used chatGPT to help me with a first pass at the algorithm and then went through and rewrote all the code so I could understand it and incorporate it into my agents code efficiently. The AI implementation was re-doing a lot of work that had already been done at the agent stage, like finding the intersections. Fun fact: as I recoded it, I was able to bring it down from 444 lines to around 120, before any real attempts at minifying. While the Agents Walk Let’s take a look at a simplified version with just a couple of paths and a bigger distance between the points, so we can see what’s going on. There is a path that goes around the edge of the canvas, enclosing everything. Usually this is right along the edge but I’ve pulled it in a little so it’s visible. Simple version with two wandering paths plus an outer path Let’s zoom in on what’s happening where the two wandering paths intersect. In the images below, we can see that the pink path was created first because the ID numbers of the points are lower. When the blue path came along, it tried to go from point 53 to the location shown with the grey dashed line (first image), which would have been point 54. However, that collides with the existing pink path. Simply stopping at point 53 would create a loose end. Instead, we adjust the position of point 54 to be exactly at the intersection (second image). Blue tried to draw a point but collided with pink New point is moved to be at the intersection While the agents are creating these non-intersecting paths, we’ll save the information that we’ll use later to create the shapes. To create the shapes we’ll need: A collection of points As the Agents create their paths, they also add each point to a shared list. A collection of connections between the points The agents add the connections between the points (e.g. 21-22, 22-23, 23-24) to another shared list. When we put the shapes together, we’ll need to know the angle of each of these connections. We already have this information, because the agent used an angle to know which direction to travel in for each new point. These angles are saved with each connection, so we won’t have to spend time calculating them again. No intersecting connections This is also handled already! As we’ve just seen, an agent never puts down a point that creates an intersection with an existing path, it moves it instead. When we moved point 53, we put it right in the middle of the join between point 22 and 23. In the images below, each join has a different colour and in the second image we can see that the join between 22 and 23 has been split into two, creating a connection between 22-54 and 23-54. Before point 54 Point 54 is placed, splitting the connection between 22 and 23 By the time the agents have completed the paths, we have an list of points and a list of the connections between them, none of which intersect. These things make up a “planar graph". Using the graph Now we’re going to use that planar graph to find all the enclosed shapes in our paths. We want to go from the disconnected paths (on the left below), to the connected shapes (on the right). From paths to shapes The next step is to go through the list of connections and turn each one into two “half-edges”. A connection is made of two points, say 54 and 53, but it’s not just from 54 to 53, it’s also the other way around - from 53 to 54. Each connection is made up of two connections, each one is known as a “half-edge”. In the image below, the original connections are in grey. The half-edges are in yellow and purple pairs. Depiction of half-edges Note that the half-edges actually exist exactly along the paths, I moved them outwards only to visualise them. It doesn’t matter which one is yellow and purple in each pair, there are no “types” of half-edge, they’re just pairs going in opposite directions. One half-edge has the angle we saved with the connection, the other has that angle flipped (we add 180°). Finding the way Pick any half-edge in the image below as a starting point, follow the arrows anti-clockwise and, whenever you reach a junction, take the left-most turn. Eventually you’ll end up back where you started, having travelled around one entire shape. Half-edge paths That’s what we’re going to do to find the shapes, but currently the computer won’t know which half-edge is “left” when we get to a junction, so we need to figure it out. To do this, we prepare by going through each point and ordering its outgoing half-edges by angle. We already have those angles saved with the half-edges, so at this step it’s just a case of putting them in order. Point 54 (below) has 3 outgoing half-edges. 0° is down, so half-edge 111 is at 96°, half-edge 47 is at 116°, half-edge 113 is at 256°. Angles of the outgoing half-edges at point 54 Once we’ve prepared this information for every junction, we work our way through all the half-edges, figuring out where to travel to next. When a point only has two connections, it’s easy, we just follow the path we didn’t come in on! When there’s a junction, we use the angles to figure out the left turn. Looking at the image below, we’re coming into point 54 on half-edge 110. 111 is the twin of 110, so we know we won’t be going out on that one, but we’ll use it to find the left turn. From 111, if we look around the available outgoing half-edges clockwise (which we can do easily because we’ve already put them in order), the first one we come to is the left turn. In this case, when we look clockwise from 111 we come to 113. That’s the left turn and will be our next step. Travelling in to point 54 on half-edge 110 Let’s do another example. Now we’re putting together a different shape and we’re coming into point 54 on half-edge 46. 46’s twin is 47, so we look clockwise from there and find 111, which is the left turn. Travelling in to point 54 on half edge 46 Building Loops Now all that’s left is to go though every half-edge, building paths by following the next steps we’ve figured out. As we go past each half-edge we mark it as “visited” and when we hit a half-edge that’s already been visited, we are back to the beginning of the shape. Then we look for another half-edge that hasn’t been visited again, to start tracing around another shape. Once all the half-edges have been visited, we’ve used all the planar graph information, and we have all our shapes! Depiction of the shapes In this image I’ve adjusted the position of each shape’s path so you can see the separation. The adjacent paths for each shape are in fact tracing the same line. I wanted to show this because it demonstrates that there is one giant shape around the outside. We don’t want that one, so it is deleted simply by looking for the largest shape by area. Now we have 3 shapes that can each be filled with a different colour. Filled shapes Back to complexity That’s cool but it’s much cooler with lots of shapes! Work in progress output Work in progress output Work in progress output In each image, I’m altering the settings within the agents, so that they use Perlin noise in different ways as they create the initial paths. Sometimes different settings are chosen based on the area the agent starts from, sometimes settings are changed when an agent has covered a certain distance, and more. Colours are chosen for each shape based on position. I use a library called Spectral.js to mix together the colour for each shape. Perhaps I’ll do another article about the way colours are placed. Let me know if that’s something you’d be interested in! Work in progress output Work in progress output I hope you enjoyed this article! If you’d like to read more like this, you can sign up to my newsletter below. If you like my work, I have prints and original artworks available in my shop. Feel free to reach out with any questions and let me know what you think! Meaningful Nonsense 02 from £35.00 Handwriting Spiral 2 (8x10") £80.00 Sold Handwriting Spiral 1 (8x8") £80.00
This series continues my explorations of the ways meaning can emerge from randomness. Each image is created using algorithmic systems that create the elements. There is an alphabet of symbols, a message generator and several approaches to glitch aesthetics. The result could be meaningful, or could be nonsense. This article unpacks the components of the system: how the symbols are placed and distorted, how the sentences are constructed, and how variation is managed across the 3001 outputs. It also explores the underlying questions of what happens when randomness is shaped into something that feels like a message and how building these systems could enable meaning to reach us. A Message Drifts test output A Message Drifts test output A Message Drifts test output A Message Drifts test output Symbolic A Message Drifts began with the idea of a grid of symbols. Here are a couple of the very first ‘Work In Progress’ outputs I created when I started the project. Early work in progress Early work in progress The final piece has an “alphabet” of 16 symbol options. Symbol alphabet Each of the symbols is defined by a short function that lays out its basic points and offers some level of variety within the way it is produced. For example, the next image contains different variations of the same symbol. Variety within symbols After creating the basic paths, I run them through a class I created called NaturalLine. I have been using this same class in different projects for a while. It adds extra points in to a path and jitters them using Perlin Noise, creating a more nuanced and natural effect. In the images below you can see a close up of these natural lines, compared to a version where I simply drew the original input paths. It’s a subtle difference but makes the whole image seem more organic. Natural lines Original inputs Most of the symbols are positioned on an angle, which is defined by a Perlin Noise field. This creates a cohesive flow over the image. In the first image below you can see the effects of this flow field, while in the second you can see how it would look if the symbols were angled randomly. I didn’t include the option for random angling in the final piece because I felt the momentum created in the aligned image better matched my ideas for the project. Symbols positioned on angles defined by flow field Symbols positioned on random angles One of the symbols in the first image below is particularly effective with the flow field effect, as the symbol is larger and extends out of its grid cell location. The symbols shown in the second image below are not affected by angles, and always appear upright. Symbols positioned on angles defined by flow field Upright symbols There are four symbols which always appear aligned horizontally or vertically, but which can be extended beyond their grid cell location: a rectangle, a sin wave, a triangle wave (zig zag) and a square wave. The waves are always extended out across a few cell locations, while the rectangle can either extend or sit within one cell as a square. Square / rectangle symbol Sin wave symbol Triangle wave symbol Square wave symbol Each image has a different distribution of symbols. In some outputs, each symbol in the alphabet is given a likelihood of being chosen. The likelihood for any given symbol could be zero, so each output has a different selection of symbols with different distributions. There are also some outputs which use a curated selection of symbols. In the first image below, there are only two symbol types while the second image has many different symbols. A Message Drifts test output A Message Drifts test output Grid The symbols are arranged in a grid, which can have margins of different sizes and types. In the example images below, I’ve turned off some additional features so the grid edges appear more clearly. No margin Solid margin Margin is solid at the top and uneven at the bottom Margin is uneven at top and bottom Symbols can also be jittered away from their original positions, using a Perlin Noise field, in a few different ways. Here’s a direct comparison using the same seed (again, with some other features turned off) No position adjustment Gentle Mixed chaos Smooth chaos Scattered positions Glow You might have noticed that everything in the images is glowing! The library I’m using in JavaScript (p5js) has a built in blur filter feature, but it is extremely slow and doesn’t offer a lot of control over the results. Instead of using that, I create the glow by drawing extra iterations of the content at a lower opacity. Every line or shape is drawn multiple extra times at slightly larger sizes than the original, with lower and lower opacity at the larger sizes. The first image below is an unedited close up of an output. In the second image, to visualise what’s going on, I adjusted the glow effect so instead of 20 extra versions of each symbol, there are only 4 and they appear clearly. Glow close up Adjusted glow close up Messages Vitally, each image in the series contains a short message. These sentences are generated, not using AI, but with an algorithm I wrote. The algorithm first selects a sentence template, from a set of about 40 possibilities. Here are a few examples. [ ["nouns", " are ", "adj", " and ", "adj"], ["nouns", " are ", "adj", " and ", "adverb", " ", "adj"], ["noun", " is ", "adj", " and ", "adverb", " ", "adj"], ["nouns", " ", "verb_plur_prep", " ", "nouns"], ["nouns", " ", "adverb", " ", "verb_plur_prep", " ", "nouns"], ["There is ", "noun", " in ", "adj", " ", "noun"], ]; The algorithm then populates the sentence with the appropriate parts of speech, chosen randomly from my curated word lists. As the words are added, various grammatical rules are applied so that the sentence flows correctly. (The following outputs have been cropped to focus on the sentence) Sentence with a preposition Prepositions This image’s sentence is formed using the following structure: ["nouns", " ", "verb_plur_prep", " ", "nouns"] The verb list contains words like “see”, “analyse” and “think”. Some of these words could slot into the sentence by themselves. For example: “Molecules see phenomena” or “Molecules analyse phenomena”. But we can’t really say “Molecules think phenomena”. Some verbs are linked with a preposition from this list this.preps = [ "", "with", "into", "in", "to", "for", "about", "on", "from", "as", "by", "through", "towards", "onto", "at", "within", "of", "between", "across", "among", "over", "like" ] “Molecules think phenomena” then becomes “Molecules think about phenomena”. Conjugated verb Single and plural nouns Words in the noun list come with information on how to handle their pluralisation. Most nouns can be used as plural or singles. Single nouns have information about what article should be used, for example “A memory”, “The void”, or simply “time”. Some nouns cannot be pluralised, for example “weather”, “balance” and “faith”. Verbs are also conjugated into two separate lists, to work with singular or plural nouns. For example we’d say “A memory conceals…” but “Memories conceal…” Sentence with an adverb Adverbs I recently added adverbs to my grammar algorithms, opening up a new set of sentence structures. All of my adjectives, e.g. “phenomenological”, “anecdotal”, “cryptic” now come with information on how to turn them into adverbs. I.e. some need “-ly” added, some it’s “-ally” and so on. This means I can now not only describe nouns as cryptic, but also describe actions as being done cryptically. If you’d like to read more about how I generate sentences, I have a whole article about it here. Handwriting Perhaps you’ve noticed that the messages look handwritten. I coded a version of my handwriting which I’ve used in several projects now. I started by defining just a few points for each letter’s paths, and including a 2-3 options for each letter. I based these paths on my own handwriting. Here’s how a message looks with just the initial points that define each letter. Initial letter points Next, the letter paths are curved, using Chaikin’s curve algorithm, and joined together, so they look like this: Letters curved and joined into words Lastly, the word paths are turned into shapes, so they can be given different weights along the path. The paths are slightly thicker towards the bottom of the letters. The paths are also tilted, for an italic effect, and the glow is added. “Handwritten” text If you’re interesting in more on this topic, I have two articles which go into more depth about how I coded my handwriting. The first article is about my initial implementation, in which I had individual letters rather than joined up or cursive writing, but it does go into detail about Chaikin’s curve algorithm and turning the paths into shapes. In the second article I go into detail about how I coded my own handwriting, including joining the letters together into natural paths. Glitching out (features) At this point, we have created a grid of glowing symbols and a mysterious message. WIth just this, here’s how the outputs would be looking: Image with no additional features Image with no additional features To develop the project further, I incorporated glitch aesthetics. Repetition The gridded symbols can be duplicated. There are different methods for the positioning of the duplicates. Here are some examples: “Long” - lines in horizontal and vertical directions “All directions” - horizontal, vertical and diagonal lines “Smudge” - shorter lines with symbols closer together “Up and down” - positions jittered along the lines “Wander” - smooth wandering waves “On the spot” - smattered around the original location Stretch Symbols can be stretched horizontally, vertically or radially. The lines created as they are stretched can be manipulated in different ways. Here are some examples. Radial - no jitter Vertical - gentle jitter Horizontal - mega jitter Vertical - small jitter Radial - tiny jitter Vertical - wide smooth jitter Passing Lines Additional flowing or jagged lines can be added to the image, passing through the grid. These are adapted from an element I have used before, in my project Tiny Endless Things. There are several different aesthetics available for these lines, here are some examples: jaggy light many squiggles messy small smooth swoop Every output has at least one of the features - repetition, stretching or additional lines. Many have two of them, repetition and stretching, or repetition and lines. Stretching and the additional lines cannot be combined as stretching the symbols also creates lines of a sort, and so combining them created clashes. Repetition and lines Repetition and stretching Large symbols An additional subtle feature is the chance for symbols to be enlarged. Around 1in 10 outputs have this possibility turned on, but only certain symbols can be enlarged. Output with enlarged symbols Output with enlarged symbols Option Management I have a couple of functions I use to make choices from sets of options. One returns a choice completely at random and one returns a choice with different weightings of likelihood taken into account. // equal choice function ecx(options){ return options[int(rand(options.length))]; } // weighted choice function wcx(options) { let opt = []; for (let o of options){ for (let i = 0; i The equal weighting option chooser is simply passed an array of options, while the weighted option chooser is passed an array that contains inner arrays which contain the option and a number to define how each option should be weighted. For example, here is the options array for the functions: sx.features = wcx([[["repeat"], 2], [["stretch"], 2], [["lines"], 1], [["repeat", "stretch"], 9], [["repeat", "lines"], 5]]) Given 1900 outputs the options would be distributed roughly like so: 200 repeat only 200 stretch only 100 lines only 900 repeat and stretch 500 repeat and lines Where options affect each other, I tend to set them up in groups. For example, here are three of the six options for the way repeated symbols can be laid out. op.repeatOptions = [ [{ name: "on the spot", on: true, glitchChance: 0.12, glitchDistances: [3, 1], directions: [1, 0], jitter: 30, alpha: { start: 60, end: 20 }, numRepeats: () => { return rand(10, 19); } },1], [{ name: "smudge", on: true, glitchChance: 0.1, glitchDistances: [3, 8], directions: [1, 0], alpha: { start: 60, end: 10 }, numRepeats: () => { return rand(20, 60); } }, 2], [{ name: "wander", on: true, glitchChance: 0.1, glitchDistances: [15], directions: ecx([[1, 0], [0], [1]]), noise: { res: 0.003, dist: 100 }, alpha: { start: 60, end: 0 }, numRepeats: () => { return rand(20, 50); } }, 1], ] It would be possible to randomly generate values for each of these settings individually (glitchChance, glitchDistances, directions) etc. But by grouping them together, I create notably different sets of outcomes and ensure that the combinations always work together. As an example - in an output where repeats are done using the “smudge” settings, each symbol will be repeated between 20 and 60 times, while an output with “on the spot” settings will repeat each symbol between 10 and 19 times. This level of control is important. For example, when repeating symbols “on the spot”, it can become blocky if they are repeated as many as 60 times, but if the “smudge” option repeated symbols only up to 19 times, we don’t get nice long trails of smudgy repeats. “on the spot” with too many repeats “smudge” with too few repeats There are also some layers of additional randomness within the options. For example, in the “wander” option, the direction of the repeats can be horizontal [0], vertically [1], or both [0, 1]. The choice of available directions is made once for the whole image and then each symbol that is repeated then makes a choice from those options, therefore either all going horizontally, all vertically or some of each. There is also variety within the images - for example, every symbol that is repeated calls the function for numRepeats individually, so each set of repeat is different. Collisions As in many of my projects, there is a system for managing collisions between elements. First of all, symbols need to give way so that the messages can be read. Additionally, due to the way symbols are moved from their original gridded positions, stretched, repeated and enlarged, they can collide with each other. Some of these collisions are desired but not all. There are several different settings for the amount of collisions allowed, which also vary depending on the element type (e.g. repeated and stretched items are generally allowed more collisions than originals) and the grid size. Some outputs also naturally have more collisions than others due to the grid layout, symbol types and features. None Spaced Mid Many I explored several different ways of clearing space for the text, including removing entire symbols, moving them away from the text, fading their opacity and cutting away parts of the symbol. In the end I settled on a combination of the latter two methods. Symbols making way for text If symbols did not make way for text In the live code outputs, it’s possible to hit the “a” key to see all elements including those which have been removed (although it does not replace points which have been cut away from the text), and to hit "d” for debug mode, which illustrates the locations of the collision detection points. In debug mode, most collision points appear in green, while the points for elements which have been removed appear in red and those which have areas cut away for the text appear in yellow. Output All elements Debug mode Palettes Here are the 20 palettes available! acid replay bzzzzz warm chalk citrus deep circuits electric garden heat monochrome in highlight parrot specific Colours can be laid out in three ways Random colour layout Perlin noise colour layout Gradient colour layout Concept Ideally, these images appear as if they are transmissions, arriving from somewhere. The question of authorship runs through all generative work - as generative artists we relinquish control to the systems we have created and to randomness. In this piece in particular, I hope that question is near to the surface. The combination of organic aesthetics like the handwriting and digital aesthetics like the glitch, glow and repetition point to this mystery. Where did these communications originate from - myself as the artist, the system I created, or something else? You know that the words are chosen at random and there is no logical reason they should say anything significant. Yet the messages are suggestive of meaning and, if you choose to interpret them with sincerity, then value can be found. We exist in a universe where we are frequently left to our own interpretations of meaning, without any intrinsic or prescribed purpose. I find randomness to create an abundant supply of suggested meaning, of hints and signs and clues which we can construe as we wish. I believe strongly that using systems to generate random “nonsense” can create a surface on which to find things that resonate and mean something to us. More quietly, I question, if the universe was to directly send a message, might it use a system such as this? A Message Drifts test output A Message Drifts test output
Over the past few weeks, I've been experimenting with painting in watercolours using my AxiDraw plotter. Watercolour is a medium I enjoy painting in (by hand) as a personal hobby, kind of separate from my public art making, so it’s been interesting to combine it with code. I’ve thought about trying this for a while but I was finally spurred on to do it after I visited Licia He’s studio in April. This article is not intended as a tutorial, but more of a scrapbook of what I’ve been trying, the results I’ve created and the mistakes I’ve made (and continue to make). Set up There are a variety of ways to control an AxiDraw plotter. I do it by creating svgs using JavaScript. I open the svg in Inkscape and use the AxiDraw plugin to control the plotter. If you’re wondering how to create an svg in JavaScript - I wrote my own class to do this, after finding that other libraries weren’t working as expected for me. My svg builder is on github and you can feel free to use it. An svg is essentially a series of paths. Usually a plotter moves a pen around those paths. When plotting with watercolour, we also need to create paths to pick up paint, swirl the brush in water and dab the brush on paper towel. Here’s what my set up looks like in real life, with all the equipment taped in place next to the plotter. Watercolour set up in real life I’ve mirrored the real world set up in code. Doing this required a bit of trial and error to make sure things were placed in the right place, but it wasn’t as finicky as I expected it might be. There is a decent margin for error since the areas for the paints, paper and water are relatively large. Watercolour set up in code This output would paint a series of vertical wavy lines on the paper. The blues and greens represent the colours that will be painted, while the thin red line represents the path that will be exported as an svg, for the paintbrush to follow. Notice that there are red circles around the paint areas, lines in the water area, and dabs on the paper. These are all added to the svg in order, so the paint brush will: Swish through a long path in the water Dab the paper towel Circle around one of the paints Swish a short path in the water Paint one vertical line This then repeats for each of the vertical lines. Testing testing Here are the very first watercolour tests I plotted. You can see there are issues with the colour fading out, where the paint has not been refreshed often enough. Or with the results becoming uneven and “scratchy”, where the brush does not have enough water on it. I’ve experimented a lot with the order of actions described above, because picking up more or less water before or after picking up paint makes a difference to the effects created. Brushes In those initial tests I was working with a thin brush, with the bristles cut very short. My thinking was that this might allow for detail but, in fact, the bristles spread outwards, creating visible bristly edges, which I hate the look of. I’ve done some testing with different brushes. Brush 1 is the one I cut short, resulting in a scratchy line. Brush 2 and 3 are similar, but 3 performs ‘better’ - note the defined gap in the centre of the ‘a’ and the correct alignment on the start/end of the circles. A long brush can lead to “inaccurate” shapes, due to the way the bristles are dragged over the paper and become pushed around - you can see what I mean in the 4c photograph below, where the bristles are dragged from the left to the right. This effect can be reduced by carefully setting the height of the brush so that the tip only just touches the paper and by using brushes with firmer bristles. Brush 3’s bristles are much more collected than brush 2’s. Many of these brushes are flat and I placed them diagonally in the plotter. Particularly with brush 3, you can see how this results in thinner lines in the / orientation and thicker ones in the \ orientation, creating a calligraphic effect. The last four tests on the first sheet all use brush 4, but I altered other conditions: 4a - Speed 70%, brush placed with tip just touching paper 4b - Speed 20%, brush placed with tip just touching paper 4c - Speed 20%, brush placed lower down 4d - Speed 20%, brush placed lower down and weight applied The difference between the results of a and b shows that a slower plotter speed can help more paint reach the paper and create clearer lines. The difference in height of the brush in each of these is only a few millimetres but the difference in the results is marked, demonstrating how this process is (happily) difficult to control and filled with chaos introduced by the medium. Brush 4 has been damaged a bit by test 4d, where the brush was weighted down. It’s visible in the photo of the brushes above - the bristles were neater before the tests. I do like the smushy effect of the circle though, it could be interesting to play with that. Brushes 5, 6, and 7 are wider but it’s still possible to write readable words, just at a larger size. The diagonal orientation effect of the diagonal flat brush is also more pronounced here. The first shape on Brush 7 uses the same circular path as all the other brushes - the bristles in contact with the paper just haven’t moved that much. Wider brushes generally lend themselves to smoother edges and no risk of scratchy areas, while thinner brushes are obviously necessary to create detail. I’ve been on the look out for brushes in the shape of brush 3, but shorter and narrower. I also haven’t yet experimented much with brushes of different shapes. This is an ongoing exploration! Smooth lines The first “proper” outputs I created were these Perlin noise adjusted rows of lines. It’s interesting that in the tests of the thinner brushes, the colour often runs out before the end of the word or even the short sine wave. Whereas in these outputs, a slightly wider brush manages to continue the full length of a sheet of A4 paper. Even a small difference to the width of the brush seems to make a big difference to how much water and paint it can hold. Watercolour Words I’ve tried a few different ways of creating typographic pieces, using the handwriting I coded in Javascript (you can read about that here). In this first one I simply repeated the same word in different shades, using a large brush. I particularly like the areas where one word bleeds into its neighbours. I’ve also experimented with using a few words or a short phrase, in different layouts. I love aspects of these, but they don’t quite feel like “finished” pieces, due to the amount of white space. One thing I’m particularly liking is the smudged areas of colour. I dripped water onto the paper by hand as the plotter was working, so that the paint would run. In this video you can see the drips of water on the paper and how the colour spreads and distorts as the brush moves through one of them. I love how this takes advantage of the watercolour medium. In some of these next pieces, I automated this by drawing circles (actually I used the letter ‘o’) in water ahead of the main letters in paint. In this video you can see the ‘o’s drawn in water - showing up as pale purple as the water tray had taken on a good amount of paint by then. As the ‘j’ is drawn, the colour spreads out into the water. These single letter typographic pieces are my favourite watercolour plots I’ve created so far. Few things make me happier than a cloudy gradient. Layering In the past couple of days, I’ve been working towards making the sentence/phrase/word pieces feel more complete by experimenting with layering. I feel like there is something interesting here, but much more refinement is needed. Creating these is a time consuming process so experimentation is slow. I’m working on better integrating the layers, so that the words or other foreground content feel naturally part of a painting. Going forward There are some practical things I need to improve upon - I haven’t been pre-soaking my watercolour paper, which means it warps when it gets wet. This is particularly problematic when trying to set the paintbrush to an exact height above the paper, because the paper is not all the same height. I’m finding the painters’ tape, which I use to create nice clean edges, often lifts up during the process. I’m hoping this may improve when the paper is pre-soaked. I need to get some much smaller brushes to try out. I also have lots of ideas for ongoing exploration! One thing I’ve just started doing but am not ready to share yet (the first test is literally in the plotter as I write this) is using photographs as inputs for representational paintings. Currently this feels like something to try out for fun rather than something I’d want to “really” use the process for - but who knows where it will go. I’m mostly thinking about ways I can make the most of the combination of the exactitude of the robotic method with the chaos of the physical medium. 😍 Enjoyed this article? I’d love it if you could give a boost on Twitter, thanks! ✨ And don’t forget to sign up for my weekly newsletter, filled with updates.
Coding my handwriting in Javascript - how I did it and what I’m doing with it.
More in creative
World Models, Astra 6, Fervo, Cybercab, Lettuce Robot, Space Telescope, PSI + Extra Doses
I’m Jay, a full-time printmaker originally from Canada but currently living in Cornwall. I use wood engraving to create intricate and narrative landscapes that explore themes of home and solitude, and our connection with the natural world and each other. Describe your printmaking process. I work primarily in wood engraving, which is a niche form of relief printing. It’s the process traditionally used to print book and newspaper illustrations, so it’s perfect for capturing small details. It’s similar to regular woodcut or linocut in that you’re removing the areas you want to keep white (drawing with light), but it uses speciality end-grain wood and engraving burins instead of carving tools. I also create collages with pieces of my wood engraving prints. I deconstruct and then reconstruct the landscapes to create a series of new compositions in collage. How and where did you learn to print? I started printmaking at NSCAD University back in Canada. I went to art school thinking I was going to be a painter, but I took my first printmaking class and was instantly hooked (and never did any more painting!). I signed up for every print class I could find. I learned lithography, etching, screenprint, typography and relief print. I actually never tried wood engraving until I came to the UK. I saw people online doing engraving, and I was really interested in the process and how they were able to get such small details. Why printmaking? I love the whole process of making prints. I’ve always been drawn to the repetitive mark-making and all the different steps of preparation involved. I can get quite anxious and stuck in my head sometimes, and I find that the satisfying and meditative processes like engraving, tearing paper, and printing editions can help me feel more relaxed. Where do you work? Currently I work from my studio in Krowji, Redruth. Describe a typical day in your studio. Honestly every day is different depending on what I have going on. Some days are big admin days filled with answering emails, making social media posts, organising work for galleries, applying for exhibitions, and my least favourite of all, doing my taxes. But on the creative days I’ll have breakfast/coffee, drive to my studio, and spend the day working on my prints. My favourite days are the ones I spend engraving. Once I have the basic composition planned out on paper, I transfer it to the woodblock and create the image slowly by building up different marks. I love watching the image emerge from the darkness. It’s exciting because I never know exactly how it will turn out. If it’s a small block I can finish in a day, but the larger ones can take a week or more. How long have you been printmaking? For around 10 years (with a few years in the middle where I was working regular jobs and not making any art). What inspires you? I’m inspired by the vast Canadian landscapes where I grew up and the rugged Cornish coastline where I live now. My landscapes explore themes of home, solitude, and our intrinsic connection to the natural world and each other. What is your favourite printmaking product? The woodblocks. I love them as beautiful objects in themselves. And they’re so satisfying to work with. Sometimes I like them more than the prints! What have you made that you are most proud of? To be honest, I’m quite self-critical, and I’m always looking ahead to my next work. When I look back, I can see parts of different pieces that I like, but I also see everything that I would do differently. Maybe I’ll answer that I’m most proud of my growth as an artist, and that I’ve been able to find my own niche and style, and build a life for myself where I can be creative and self-employed. Where can we see your work? Where do you sell? I share a lot of the process on my Instagram page, and I sell through my website. If you want to see my work in person, I show with Cambridge Contemporary Crafts in Cambridge, The Biscuit Factory in Newcastle, Mōr Studio in North Yorkshire, and The Poly Guild in Falmouth, Cornwall, as well as other group shows around the UK. I’m also a member of the Society of Wood Engravers, which has an annual exhibition that tours different venues in the UK so keep an eye out for that! Maybe it will come to your city. What will we be seeing from you next? I’m excited to make some large scale work this year. I’m looking forward to pushing myself to work larger and get more expressive with my mark-making. Do you have any advice for other printmakers and creatives? My advice for other printmakers and creatives (and myself!) is to not let perfectionism paralyse you. It’s okay to make ‘bad’ work, and to try things and have them not turn out. Just keep showing up and making things regularly, and something good and meaningful will emerge. To see more from Jay, follow him on Instagram! Feeling inspired? If you want to try out wood engraving, have a look at our website where we have everything you need to get started!
Measuring the box-office impact of movie trailers and the cultural value that numbers can’t quite capture.
Apophenia is the uniquely human tendency to perceive meaningful patterns or connections in random or unrelated data, events, or objects. Humans are story telling machines. And one thing we do is turn co-incident events into more than coincidences. When we see faces and shapes in clouds, apophenia wastes our time in the form of pareidolia. […]