Geometric Art in Tableau
One of my more popular projects this year was Creating Loom Art in Tableau. I wasn’t sure how people would react to it, but was pleased with its reception. After posting it, Josh Tapley mentioned that it reminded him of a tool he encountered called Geometrize when attempting to recreate Andy Cotgreave’s Kraken Art (if you haven’t read Andy’s post on this, then you definitely need to check it out—it’s brilliant!). Geometrize is an open-source tool, written by Sam Twidale, which converts any image into “geometric primitives” (rectangles, triangles, and ellipses). The tool allows you to upload your own image, specify what types of shapes you’d like to use and how many shapes should be rendered. Once the image has been created, you can download it as a PNG or SVG file.
After playing with the tool a bit, I was completely fascinated by it. It’s really quite amazing. And, of course, I decided that I had to find a way to visualize the resulting images in Tableau. So, in this post, I’m going to share the journey that I took to create these in Tableau and, at the end, I’ll give you a tutorial on how to create them yourself.
Scalable Vector Graphics
Before we jump into this, it’s important to talk a little about Scalable Vector Graphics (SVG) files as these will be critical to getting these images into Tableau. SVG files are basically XML-based files which define an image. An SVG file defines a variety of shapes that are used to build an image—basic shapes, lines, polygons, etc.—as well as coloring, shading, and a lots of other components of images. Because they are XML, SVG files are text-based and, for the most part, readable by humans. So, in order to extract the “geometric primitives” from the images we’ve created, the first step will be to export our rendered image into SVG format, which we’ll then break into its component shapes.
Proof-of-Concept
The Geometrize tool allows you to create images from lots of different types of shapes, but I wanted to keep things simple for my proof-of-concept, so I decided to generate an image made up of only circles/bubbles. Once the tool had generated my image, I exported it to SVG, then opened the SVG to see how it looked. It basically consisted of a series of circle objects defined like this:
<circle cx="184" cy="543" r="65" fill="rgb(255,255,255)" fill-opacity="0.50196078"></circle>
It’s relatively easy to decipher the meaning of each of these as follows:
- cx – x coordinate of the circle’s center.
- cy – y coordinate of the circle’s center.
- r – Circle’s radius.
- fill – Fill color in RGB.
- fill-opacity – Opacity/transparency of the fill color (this can actually be adjusted in the tool’s settings, but will remain consistent throughout all objects in the file).
So, if I could get each circle into its own row and each of the five components into its own column, the data would be shaped in a way that is conducive to visualizing in Tableau. But how to do this? After a bit of Googling, I found an online XML to Excel Converter. I uploaded my SVG and then converted the file to Excel. The resulting file looked like this:
With a little bit of Excel work, I was able to parse out the RGB values, then convert them to Hex using the same VBA code I used in my post on Recreating The Scream in Tableau. Note: In the “How To” section, I’ve included a link to a spreadsheet template which contains the parsing formulas and the RGB to Hex VBA code.
Using the Hex color, I built a custom Tableau color palette. I was now ready to visualize the data in Tableau. I connected to my data and attempted to visualize each cx/cy point as circles. Since Tableau sizes circles by area, I had to create a calculated field, based on the radius. The area of a circle is defined as π r2 so my formula, in Tableau, is as follows:
PI()*SQUARE([_R])
I used this field, which I called Circle Area, to size each circle. I then applied my color palette to each circle, changed the transparency to 50% and I had a nice bubble art image of one of my favorite artworks, The Great Wave Off Kanagawa:
But, I quickly found a couple of problems with this approach. First, I had to manually adjust the overall Size of the bubbles to make sure they were just right. Second, because there is a maximum shape size in Tableau, the final images were all quite small even at the maximum size.
Bubble Polygons
In order to address these problems, I decided that I’d need to draw each circle in a more precise fashion. Enter parametric equations. In my recent post on creating curves in Tableau using parametric equations, I explained how to use these equations to create a circle. So, I applied that same concept in order to draw individual circles, coloring them the same way as in my first attempt.
Each circle is actually a polygon with 100 different points. Typically, I’d use more points for a circle in order to prevent them from looking blocky, but most of the circles are relatively small, so I was able to get away with only 100. And, by keeping this number small, the image renders much more quickly.
I personally like watching these “build” from a blank palette, so here’s an animated gif of a different artwork. See how long it takes you to recognize it.
As an added bonus, I used an adjustable bins technique to allow you to change the number of points to be anywhere from 3 points (which would generate an isosceles triangle instead of a circle) to 100 points. For example, here’s the image using polygons with 4 points:
All Shapes
Now, having conquered the bubbles, I felt I was finally ready to create images using all the shapes allowed by Geometrize. These include rectangles, rotated rectangles, triangles, ellipses, rotated ellipses, and circles (Note: Geometrize actually includes lines as well, but I have decided to exclude those and focus only on actual shapes). The problem, however, is that the structure of the SVG elements are quite different for each of these different object types. For example, a regular rectangle is created in SVG using a “rect” object, which includes the coordinates of the top left point, plus height, and width. But a rotated rectangle is generated using a “polygon points” object which lists the coordinates of all four points of the rectangle. This being the case, I wasn’t going to be able to use Excel formulas and macros to extract the data. So, I decided that I’d need to write a bit of code.
The good news is that I have a background in programming. The bad news is that it’s been a long time since I’ve written code on a regular basis and much of my work experience has been with fourth-generation languages built into ERP systems. But, based on some conversations with Brit Cava and Rody Zakovich, I had been intending to learn Python, so what better way to learn than to jump right in!!
The basic idea would be to read each object from the SVG, then create polygons for each of them, writing these polygons to a csv file. If you’re interested, here’s some high-level pseudocode.
1) Open the SVG file.
2) Parse out each object.
3) For each object, parse out each of its components.
4) Process each object type as follows:
- Rectangles – Write each of the four points to the polygon csv file.
- Polygon Points (Rotated Rectangles and Triangles) – Write each polygon point to the polygon csv file.
- Ellipses (Including Rotated Ellipses and Circles) – Use parametric equations to create 100 point ellipses and write those points to the polygon csv file (Again, if you’re not familiar with parametric equations, check out my recent post on using them in Tableau).
5) Along the way, for each shape, translate the fill color from RGB to Hex and write the color to a separate csv.
After picking away at it for a few days, I was able to create a program to do exactly this. Not bad for my first Python program!!! I’m not going to go into any more detail about the code itself, but if you’re curious, you can find it on my GitHub repository.
With my program finished, I generated an SVG using Geometrize, including all shape types (except lines) and then ran it through the code. With the resulting color csv, I created my custom color palette. Then, in Tableau, I connected to the polygon csv and created my polygons. Here’s the result:
So, how did I do this? Well, check out the following How To section for step-by-step instructions.
How To
I’ve detailed three different methods for creating geometric art in Tableau, so I’m going to provide a tutorial on all three. All three have the same steps for generating the SVG, so let’s start with those basic steps first:
Geometrizing Your Image
2) Click the Settings option in the middle of the screen.
3) Select the shapes you’d like to include. If using methods 1 or 2, then only select circles. If using method 3, you can select any combination of shapes you like, except lines.
4) Below the list of shapes, set the Max Shapes Cap. The default is 7,000 but everything I’ve created, including templates I’ll be providing here, used a maximum of 5,000.
5) Scroll down and select the Open Image option then select the image you’d like to process.
6) If it does not start generating shapes, then click Run.
7) The process will take a few minutes to complete. Once it’s finished, click Save SVG to download the SVG file.
Converting SVG to Excel (Methods 1 & 2)
2) Where it says Option 1 – Choose a XML File, click Choose File, then select your SVG.
3) Scroll down to Step 3: Generate Output and select XML to Excel. And Excel file will be downloaded.
4) Open the Excel file and paste it into columns B – F in the Excel template, Template.xlsm.
5) Use the values in column N to generate a custom categorical color palette in Tableau (for more details on this, see Create Custom Color Palettes on the Tableau Online Help site).
A few notes about the Excel template:
- The template is a macro-enabled spreadsheet, so you’ll need to enable macros when you open it.
- It is configured for 5,000 points, so if you’ve created an SVG with more than 5,000, you may need to copy some formulas, etc. to additional rows.
- The template has two sheets, Shape and Range. For method 1, you’ll only need Shape. Method 2 will leverage bins and will, therefore, require the Range sheet.
Method 1: Simple Bubbles
1) Generate your Excel file and create your custom color palette using the steps detailed above, then connect to the file in Tableau.
2) Drag the Shapes sheet to the data pane.
3) Convert Circle # to a dimension.
4) Drag Circle # to the Color card, then choose your new custom color palette.
5) Change the color transparency to 50%.
6) Change the sorting of Circle # to descending (These images are created by layering shapes on top of each other, so the descending sort will ensure the proper layering).
7) Create a calculated field called Circle Area with the formula “PI()*SQUARE([_R])”.
8) Drag Circle Area to the Size card.
9) Drag _Cx to the Rows shelf and _Cyto the Columns shelf.
10) Reverse the y axis.
11) Change the shape to a filled circle.
12) Play with the sizing of your shapes until the image looks right.
13) Make other adjustments as desired including gridlines, fixed axes, etc.
Method 2: Bubbles with Parametric Equations
1) Generate your Excel file and create your custom color palette using the steps detailed above.
2) You have two options at this point. You can simply download my template workbook (Bubble Art Template) and connect it to your Excel file. Or you can move on with the following steps to build it yourself.
3) Connect to the Excel file then drag both Shapes and Range to the data pane. Join them using a join calculation where 1=1.
4) Create bins for the Range field with a bin size of 1.
5) Download the template workbook provided above and copy the following calculated fields to you workbook: Index, T, X, Y. I’m not going to go into the calcs here, but feel free to dig into them if you like.
6) Drag Range (bin) to the Detail card.
7) Convert Circle # to a dimension.
8) Drag Circle # to the Color card, then choose your new custom color palette.
9) Change the color transparency to 50%.
10) Change the sorting of Circle # to descending.
11) Drag X to the Rows shelf and Yto the Columns shelf. These will become table calcs. Change them to compute using Range (bin).
12) Reverse the y axis.
13) Change the chart to Polygon.
14) Drag T to the Path card.
15) Make other adjustments as desired including gridlines, fixed axes, etc.
Method 3: All Shapes
2) If not, you can download the executable package, ParseSVGPackage.zip. Extract all the files to your computer, then run Parse SVG.exe. Sorry Mac users, but I think this will only work for Windows, but if you really want to try this, I’m happy to help you get Python set up on your machine.
3) The program will guide you through the process of selecting a source SVG and will then output two csv files, one with color information and another with polygons.
4) Based on the color csv, create your custom color palette.
5) Connect to the polygon csv in Tableau.
6) Drag X to the Rows shelf and Yto the Columns shelf.
7) Reverse the y axis.
8) Drag Polygon ID to the Color card, then choose your new custom color palette.
9) Change the color transparency to 50%.
10) Change the sorting of Polygon ID to descending.
11) Change the chart to Polygon.
12) Drag Point ID to the Path card.
13) Make other adjustments as desired including gridlines, fixed axes, etc.
So there you go. If you create any geometric art using this method, please share with me. I’d love to see what you create!!
Ken Flerlage, December 1, 2017
Easy way out for RGB TO HEX
ReplyDelete=IF(ISODD(LEN(DEC2HEX([@R]))),"0","")&DEC2HEX([@R])&IF(ISODD(LEN(DEC2HEX([@G]))),"0","")&DEC2HEX([@G])&IF(ISODD(LEN(DEC2HEX([@B]))),"0","")&DEC2HEX([@B])
@R --> POINT R CELL
@G --> POINT G CELL
@B --> POINT B CELL
Mind blowing !!!!!!........ Truly Inspirational !!!!!
ReplyDeleteThanks Vishnu!
DeleteThanks for the insightful tutorials on Tableau! I am amazed at what you are able to do, and hope that one day I will get "your autograph".
ReplyDeleteThis is my work of art using Geometrize (took me a couple of hours, but after going through your tutorial I just could not help myself) - https://public.tableau.com/profile/alexandru.singeorsanu#!/vizhome/LemonArt/Lemonade
This looks great!
Deletemine came out as
ReplyDeletetranslate(97 94) rotate(137) scale(71 72)
is it safe to assume that translate are the cordinates x,y and scaling is some kind of representation of the radius?
I haven't seen the tool create those SVG objects. Which shape types did you choose?
DeleteThis is really awesome!!! My wife and I are both big Tableau nerds, so i re-created one of our wedding photos as part of her anniversary present. In the desktop version I have it set up with page controls so you can see the image being built. Thank you for this!!
ReplyDeletehttps://public.tableau.com/profile/brian.moore7221#!/vizhome/WeddingPhoto/Photo
Great! I'm glad you like it. I used pages to build the gif. I just set up the page control then used a free software product called ScreenToGif to capture the animation and save it off as a gif.
DeleteAnd the photo looks great!
Deletehi Kevin, fantastic tutorial! I've been working through method one for simple circles but am stuck. I have used your template to generate the Tableau palette codes in column N. However, there're about 500 unique codes for my dataset. How do you use this information to create a Tableau color palette which has a limit of about 20 colors? Also, how do you apply this palette to the Dimension #Circles in the dashboards?
ReplyDeleteTableau color palettes do not have a limit. On screen, they will only show the first 20 or so, but the rest are there. So you need to order the data according to the Circle #, then select the palette and click "Apply". That will apply all the colors, even though only some of them are visible. Does that make sense?
DeleteThe XML to Excel has columns A to G, and not B to F like in the template.xlsm file. How do I adjust the template to accommodate for the extra columns?
ReplyDeleteI wonder if they changed the tool. Would you be able to share your file with me via email? flerlagekr@gmail.com
DeleteHow do you animate those bubble graph any help will be appreciated :)
ReplyDeleteIt's a bit of work to do, to be honest. Happy to provide some details if you can email me. flerlagekr@gmail.com
DeleteThanks Ken for the blog. I've had tons of fun playing with images. I have problems with animating those bubbles. Looks like showing history is not working on a polygon chart. I placed polygon ID (or Colour ID) on Pages, and selected Show History, but Show Marks was greyed out and only one bubble showed at a time.
ReplyDeleteHmmm. Any chance you can email me? flerlagekr@gmail.com
DeleteThank you soo much for this!! Making art through data is such a good feeling. :)
ReplyDeleteThanks Ken, this has been amazing. I'm struggling to assign my colour pallet correctly - I have ordered the data but as soon as I click assign I end up with a bit of a jumbled mess. Do you know what might be going on here?
ReplyDeleteCould you email me? flerlagekr@gmail.com
DeleteHello, I love your work ! I sent you an email because I am blocked at the visualization stage. I thank you in advance for the help you will give me :)
ReplyDelete