Do you know that snowflakes are never perfectly identical? Their shape depend mainly on temperature and humidity. As there is around 10 to the power 19 water molecules in one snowflake, you can imagine how many possibilities of growing the cristal has. But the growth is not totally random, when the air is cold and saturated with water, the snowflakes tend to have more detailed shapes and dendrites. (cf. https://en.wikipedia.org/wiki/Snowflake). They also often have six branches due to the cristal molecular structure.
Based on these observations, I decided to write a python script who imitate this natural phenomenon and generate randomly as much snowflakes as you want. Each being different from the other ones.
This script is based on freeCAD so anyone can install this app and start making snow! Once the snowflake 3D model has been generated, you can easily 3D print it or cut it.
Step 1: Install the Software
Click on the link ( https://www.freecadweb.org ) and install FreeCAD.
Download the python script named "snowFlake.FCMacro" attached to this step.
Once FreeCAD is opened, on the top right corner you have a letter and pencil icon. Click on it.
Then select the path to the script you just dowloaded.
Then select "edit" if you wand to play with the parameters (size) or just "Execute". You have the same result if you click on the green play button once the path is selected.
Wait around one minute (sometimes less, sometimes more). Then the snowflake appears but you may not see it because it doesn't fit the screen: just click on the magnifying glass icon on the top left corner. (with a mouse, you can also scroll up and down to zoom and dezoom).
You don't like the result? Just close the snowflake window and run the script again!
Step 2: Make It Real
Now that you have a 3D model, you probably want to materialize it. Depending on your tools, machines, money and sensibility. You can either 3D print, manually cut, automatically cut or just print the snowflakes.
As there is a laser cutter in the FabLab (http://fablab77.ru/#/) next to my place, I chose this method. I also wanted to make them out of transparent plexiglass to imitate ice and to have nice reflexions inside the material.
I exported the top face in DXF and send it to the laser cutter. If you want to print it, just export in STL file.
Step 3: How Does It Work?
The first part of the code draw a polygone based on six vector. The shape is like a double arrow.
- V1 = Base.Vector(0,W,0)
- V2 = Base.Vector(L,W,0)
- V3 = Base.Vector(L,-W,0)
- V4 = Base.Vector(0,-W,0)
- V5 = Base.Vector(L+1,0,0)
- V6 = Base.Vector(0-1,0,0)
- branchL = Part.makePolygon([V1,V2,V5,V3,V4,V6,V1])
Then I extrude the polygone (pass from 2D to 3D)
- branchW = Part.Wire(branchL)
- branchF = Part.Face(branchW)
- branch = branchF.extrude(Base.Vector(0,0,1))
Three times: Make a copy of this extruded polygone, reduce it by random factor and rotate it by 60 degrees and move it laterally along the first one by random distance. I want my branch symmetric so I also add the same ramification rotated by -60 degrees.
- for i in range(1,4):
- ramiL = branchL.copy()
- ramiR = branchL.copy()
- myMat = Base.Matrix()
- len = random.random()
- wid = random.uniform(0.5,1)
- ramiL = ramiL.transformGeometry(myMat)
- ramiR = ramiR.transformGeometry(myMat)
- pos = random.random()
- if i==1: if random.uniform(-1,1)>=0:
- angle = 120 else: angle = 60
- else: angle = 60 ramiL.rotate(Base.Vector(0,0,0),Base.Vector(0,0,1),angle)
- ramiL.translate(Base.Vector(30 * pos,0,0))
- ramiR.translate(Base.Vector(30 * pos,0,0))
- ramiW = Part.Wire(ramiL) ramiF = Part.Face(ramiW)
- ramil = ramiF.extrude(Base.Vector(0,0,1))
- ramiW = Part.Wire(ramiR)
- ramiF = Part.Face(ramiW)
- ramir = ramiF.extrude(Base.Vector(0,0,1))
- branch = ramil.fuse(branch)
- branch = ramir.fuse(branch)
- snflake = branch.fuse(snflake)
I copy this patern 5 times rotated by 60 degrees in order to have six similar branches equally spaced on the 360 degrees and combine them together to make one solid.
- for i in range(1,6):
- snflake = snflake.fuse(branch)
Finally I add the hanging hole, remove the unnecessary edges and show it.
- cylinder1 = Part.makeCylinder(W*2,1,Base.Vector(30,0,0),Base.Vector(0,0,1))
- snflake = snflake.fuse(cylinder1) cylinder1 = Part.makeCylinder(W,1,Base.Vector(30,0,0),Base.Vector(0,0,1)) snflake = snflake.cut(cylinder1)
- snflake = snflake.removeSplitter()
Unfortunately this last function "removeSplitter" works only with shells. This is why I can't do all the calculations in 2D and only extrude as last step. It would be much faster this way so if you have a solution, let me know.
Now you can play with the code and make it yours.