As an extra piece of information for our visualisation (and further training in Houdini), you might want to try segmenting your year rings into chunks and identifying these with text elements like below:
This way users could focus on particular moments in time, like 10 or 20 year periods, and compare changes. Before starting, have a think about what needs to be done to achieve this. Firstly we’ll need to know how many years should sit in each group/segment, as well as the size of the gap between them. Once we have this information as new parameters in our control node we can connect them to our network. After this we can implement a new font node, copied and positioned with the same parameters.
Currently our ring sizes are being controlled via the uniform scale parameter of our main copy node. We’re going to change this expression to a slightly more complex one written in Python. Before you do this, make sure you’ve added control parameters for the amount of rings in each segment (years_per_gap) and another for the gap size (gap_size). Right click in the uniform scale field of your copy node, and under expression switch the language to Python then “edit expression”. Here’s what we’ll use:
copy_num = hou.hscriptExpression("$CY") + 1
gap_size = hou.hscriptExpression("ch('../control1/gap_size')")
gap_interval = hou.hscriptExpression("ch('../control1/years_per_gap')")
if gap_interval == 1:
size = copy_num
else:
size = copy_num + int(copy_num / gap_interval) * gap_size
return size + gap_size
Our first three lines declare some variables to make things a little easier to reference. Note the syntax to access Hscript variables in Python. Head down to line 8 for the important stuff. We start with the copy number to give us a constant linear increase in numbers, and end with multiplying by our gap size. It’s the division in the middle that’s the important part. We divide our current copy number (e.g 50) by our interval, or the amount of years each segment should have. 50/6 returns 8.33, 51/6 returns 8.5, 52/6 returns 8.66 etc. To give us that jump every 6, we wrap this division in an int() function which will round down our result to the lowest whole number, giving us a series of 8’s until we hit 54/6 and return a 9. This way we can get the pattern we want.
This is wrapped in a simple if() statement that checks to see if our “years_per_gap” is equal to 1. If it is, we’ll remove all gaps and let our ring size listen to the copy number alone. This way users can slide the years_per_gap parameter all the way down to 1 to remove any gaps. Now onto the typography.
Rather than handing over all of the maths for this next part, I’ll outline the most efficient way to approach placing type in each gap. There are a number of solutions, but a great way is to start with a line and adjust its length to always stretch between the middle and edge of the visualisation, and then resample to create points in between. You’ll want to use “maximum segment length” this time and tweak its value to work with your gap sizes. This way your points won’t move as you change the total amount of years being visualised. Remember, you’ll need this to be variable, so keep adjusting your control parameters as you work to make sure your system is flexible. The math might be tricky, but keep in mind that all your values are available in the control parameter, so there’s no need to guess.
Once you have your points sorted, rig up another font SOP into a copy node using your line network as a template. Here’s what this part of my network ended up looking like:
There are a few small things happening here worth pointing out. On the right hand, side once I’ve gotten my points where I’d like them, I’ve used an add SOP to “remove geometry but keep the points” which does exactly that. We only need the points from our line to draw on, not the line itself. Coming from my font node I’m using transform to orient my text as it was upside down on a few axis, and also an extrude node just to give my text some depth. I’ve also implemented a switch node to allow users to view these yearly markers or not. The switch node takes in multiple inputs, in this case the network we just built, and an empty null node.
I’ve created a toggle parameter in my control node which returns a 0 when inactive and a 1 when active, and I’ve pasted its relative reference into my switch node, making for a nice on/off setup. You can see it in the image above as well as a number of other control parameters I’ve created.