Last active
December 12, 2025 04:55
-
-
Save kevinkhill/2b85cbe86fad153ba0788f8eaae5e81d to your computer and use it in GitHub Desktop.
Giants Causeway Generator
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // Number of rows in the tessellation | |
| rows = 20; | |
| // Number of columns in the tessellation | |
| cols = 100; | |
| // Width of each hexagonal pillar (circumradius) | |
| hex_size = 4; | |
| // Minimum height of each pillar | |
| height_min = 2; | |
| // Maximum height of each pillar | |
| height_max = 20; | |
| // Desired number of sine wave periods across the grid width | |
| num_periods = 1.5; | |
| // Randomness to add to the height of the pillars | |
| jitter_factor = 5; | |
| // This determines where along the wave the heights start | |
| angle_tweak = -45; | |
| // Dynamically calculated amplitude | |
| wave_amplitude = (height_max - height_min); // Full range of heights | |
| // Function to calculate pillar height based on a sine wave (horizontal wave) | |
| function sine_height(col) = // | |
| let( // | |
| angle = col * PI * num_periods, // Map column to sine wave angle | |
| sine_value = sin(angle + angle_tweak), // Sine value (-1 to 1) | |
| scaled_sine = (sine_value * wave_amplitude) // Scale sine to desired amplitude | |
| ) // | |
| height_min | |
| + wave_amplitude + scaled_sine; // Offset to ensure range is height_min to height_max | |
| // Function to calculate row-based height factor (linear ramp from max to min) | |
| function row_factor(row) = 1 - row / (rows - 1); | |
| // Module for creating a hexagonal pillar | |
| module hexagon_pillar(width = 5, height = 3) | |
| { | |
| linear_extrude(height) | |
| { | |
| polygon(points = [[width * cos(0), width * sin(0)], // | |
| [width * cos(60), width * sin(60)], // | |
| [width * cos(120), width * sin(120)], // | |
| [width * cos(180), width * sin(180)], // | |
| [width * cos(240), width * sin(240)], // | |
| [width * cos(300), width * sin(300)]]); | |
| } | |
| } | |
| // Generate the tessellation | |
| for (row = [0:rows - 1]) | |
| { | |
| for (col = [0:cols - 1]) | |
| { | |
| // Calculate the x and y offsets for the hexagonal grid | |
| x_offset = col * 1.5 * hex_size; // Horizontal distance | |
| y_offset = row * sqrt(3) * hex_size + (col % 2) * (sqrt(3) * hex_size / 2); // Staggered rows | |
| // Calculate the combined height based on sine function and row factor | |
| height = sine_height(col) * row_factor(rows - row); | |
| // Add jitter for randomness | |
| jitter = rands(1, jitter_factor, 1)[0]; | |
| translate([ x_offset, y_offset, 0 ]) | |
| { | |
| hexagon_pillar(width = hex_size, height = (height_min + height + jitter)); | |
| } | |
| } | |
| } |
Author
Good catch, thank you :)
Author
Would be cool to try and make it use any 3D surface function instead of only a sin wave of linear increasing amplitude across the y dimension.
YES! ...... how?
Just want to point out that you can make a hexagon like this:
circle(d = hex_size, $fn = 6);
Author
Someone on reddit shared this with me too. I had no idea, and that's cool.
Is the sin call takes in degrees, rather than radians, what's the point of multiplying by PI on line 24?
Changing it to be angle = col / cols * num_periods and then doing sin(360 * angle + angle_tweak would mean you get definite control over the number of periods over the whole thing.
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment

Really cool! But right now the
jitter_factorvar is being ignored. Change line 61 tojitter = rands(0, jitter_factor, 1)[0];to incorporate it. Would be cool to try and make it use any 3D surface function instead of only a sin wave of linear increasing amplitude across the y dimension. Thanks for sharing!