Let's simulate a random snowflake

10

I saw this question on https://mathematica.stackexchange.com/ and I think it's pretty cool. Let's make the snowflake with other programming languages.

This is a quote from the original question:

'Tis the season... And it's about time I posed my first question on Mathematica Stack Exchange. So, here's an holiday quest for you Graphics (and P-Chem?) gurus.

What is your best code for generating a (random) snowflake? By random I mean with different shapes that will mimic the diversity exhibited by real snowflakes. Here's a link to have an idea: http://www.its.caltech.edu/~atomic/snowcrystals/ , more specifically here are the different types of snowflakes: http://www.its.caltech.edu/~atomic/snowcrystals/class/class.htm . Here we are trying to generate a single snowflake (possibly with different parameters to tune its shape), the more realistic, the better. Three dimensional renderings, for adding translucency and colors are also welcome. Unleash your fantasy, go beyond the usual fractals!

Rules:

  • Generate a random single snowflake.
  • The flake should be six-fold radial symmetry.
  • It doesn't need to be realistic. (But prefer)
  • Single character answers, like *, ⚹, ❅, ❄, ❆ are not allowed.
  • Most upvotes wins!

pt2121

Posted 2013-12-30T16:02:15.230

Reputation: 309

3Better disallow single character outputs like '*⚹❅❄❆'[Math.floor(Math.random()*5)]. – manatwork – 2013-12-30T16:06:21.633

1@nitro2k01: you realize that he referenced that exact mathematica.SE site in the very first sentence of the posting, right? – Kyle Kanos – 2013-12-30T19:09:28.867

Oops, sorry. I honestly skipped right to the rules. – nitro2k01 – 2013-12-30T19:28:46.940

Answers

14

Bash and ImageMagick

#!/bin/bash

third=()
x=90
y=90
while (( x>10 )); do
  (( dx=RANDOM%10 ))
  while :; do (( dy=RANDOM%21-10 )); (( y-dy<95 )) && (( y-dy>(x-dx)/2 )) && break; done
  third+=(
    -draw "line $x,$y $(( x-dx )),$(( y-dy ))"
    -draw "line $x,$(( 200-y )) $(( x-dx )),$(( 200-y+dy ))"
    -draw "line $(( 200-x )),$y $(( 200-x+dx )),$(( y-dy ))"
    -draw "line $(( 200-x )),$(( 200-y )) $(( 200-x+dx )),$(( 200-y+dy ))"
  )
  (( x-=dx ))
  (( y-=dy ))
done

third+=(
  -draw "line 90,90 90,110"
  -draw "line $x,$y 15,100"
  -draw "line $x,$(( 200-y )) 15,100"
  -draw "line 110,90 110,110"
  -draw "line $(( 200-x )),$y 185,100"
  -draw "line $(( 200-x )),$(( 200-y )) 185,100"
  -draw 'color 20,100 filltoborder'
  -draw 'color 180,100 filltoborder'
)

convert \
  -size '200x200' \
  xc:skyblue \
  -background skyblue \
  -stroke 'white' \
  -strokewidth 1 \
  -fill 'white' \
  -bordercolor 'white' \
  -fuzz 10% \
  "${third[@]}" \
  -rotate 120 \
  -crop '200x200' \
  "${third[@]}" \
  -rotate 120 \
  -crop '200x200' \
  "${third[@]}" \
  -draw 'ellipse 100,100 15,15 0,360' \
  x:

Sample run:

bash-4.1$ for i in {1..30}; do ./showflake.sh "showflake-$i.png"; done

bash-4.1$ montage showflake-*.png x:

snowflake montage

manatwork

Posted 2013-12-30T16:02:15.230

Reputation: 17 865

5

Javascript

Fiddle located here

More fancy Fiddle located here

It's not golfed, not by a long shot. Also required are the Perlin Noise function and seeded Random (both included in Fiddle, seeded random needed for Perlin). Fiddle also displays the current seed for keeping track of favorites ;)

function DoFlake(canvas){
    var width = canvas.width;
    var height = canvas.height;

    var ctx = canvas.getContext('2d');
    var thing = document.createElement('canvas'); thing.width = 128; thing.height = 32;
    var thingctx = thing.getContext('2d');
    var noise = new ImprovedPerlin((new Date()).getTime());

    var wDiv = 1/64;
    var y = 7/32;
    var z = 2/11;

    for(var x = 0; x < 128; x++){
        var h = 32 - (x * 32 / 128);
        h += 16 * noise.Noise(4 * x * wDiv, y, z);
        h += 8 * noise.Noise(8 * x * wDiv, y, z);
        h += 4 * noise.Noise(16 * x * wDiv, y, z);
        h += 2 * noise.Noise(32 * x * wDiv, y, z);
        h += 1 * noise.Noise(64 * x * wDiv, y, z);

        thingctx.fillRect(x, 0, 1, h);
    }

    ctx.translate(128,128);
    var angle = Math.PI / 3;
    for(var i = 0; i < 6; i++){
        ctx.rotate(angle);
        ctx.drawImage(thing, 0, 0);
        ctx.scale(1, -1)
        ctx.drawImage(thing, 0, 0);
        ctx.scale(1, -1);
    }
}

XNargaHuntress

Posted 2013-12-30T16:02:15.230

Reputation: 201

0

ZXSpectrum Basic, 21

Well, I Can't do the 6 fold symmetry, but I can get all sorts of randomness

using the ZX Spectrum: Emulator Here

Remember that keywords are a single character in the ZX Spectrum

OVER 1
PLOT 40,40
DRAW 40,40,RND*5000

To enter these commands on the emulator:

TAB ,1 ENTER
q 40,40 ENTER
w 40,40,TAB tCTRL+B5000ENTER

(Don't you just love the spectrum keyboard)

SeanC

Posted 2013-12-30T16:02:15.230

Reputation: 1 117

This does not work. It either outputs "B Integer out of range, 0:1" or renders some strange donut shape. – Lars Ebert – 2014-08-08T09:48:23.237

the bad thing about spectrum code is that plots sometimes exceed the minimal amount of screen space. alter the 3rd number in the draw to get different patterns and shapes – SeanC – 2014-08-08T12:08:09.213