Snowflake Manipulate

How can I design snowflakes with no two alike?

Initial Graphics

Generate a random real number between 0 and 10.

RandomReal[{0,10}]

Use the second argument to produce a list of coordinates. Think of {5, 2} as “5 groups of 2.” Name this list with a variable.

ptlist=RandomReal[{0,10},{5,2}]

Graphics will display the points. Note the addition of a semicolon ; after the RandomReal so we don’t see the list of points. Each time you evaluate the code below it will generate a new set of points.

ptlist=RandomReal[{0,10},{5,2}];
Graphics[{Point[ptlist]}]

Changing “Point” to “Line” will connect the points together.

ptlist=RandomReal[{0,10},{5,2}];
Graphics[{Line[ptlist]}]

Adding some options to Graphics will help display this better. Note that the options are included after the list { } within Graphics. You can type the -> with a dash - followed by a greater than > symbol.

ptlist=RandomReal[{0,10},{5,2}];
Graphics[{Line[ptlist]},PlotRange->14,Axes->True]

Let’s show the line and the points together. Include Point[...] within the Graphics list { } as below. Also, use regular Enter to create some space and start organizing the code into more readable lines.

ptlist=RandomReal[{0,10},{5,2}];
Graphics[{
Line[ptlist],
Point[ptlist]
},PlotRange->14,Axes->True]

Transformation: Reflection

Now we will reflect the line across the x-axis. This requires a GeometricTransformation along with a ReflectionTransform. The GeometricTransformation is wrapped around Line and has a second argument that says what type of transformation to do. ReflectionTransform creates a mirror that is a line through the origin normal (perpendicular) to a given vector. In this case, {0,1} would be up the y-axis and that is perpendicular to the mirror, thereby making the x-axis the mirror.

Note: We will not reflect (nor rotate) the points.

ptlist=RandomReal[{0,10},{5,2}];
Graphics[{
GeometricTransformation[Line[ptlist],ReflectionTransform[{0,1}]],
Point[ptlist]
},PlotRange->14,Axes->True]

However, that moved the line rather than looking like an original with its reflection. To also see the original, put Line[...] in the Graphics again (outside of the GeometricTransformation). Don’t forget the comma.

ptlist=RandomReal[{0,10},{5,2}];
Graphics[{
Line[ptlist],
GeometricTransformation[Line[ptlist],ReflectionTransform[{0,1}]],
Point[ptlist]
},PlotRange->14,Axes->True]

Transformation: Rotation

This part may seem a bit complicated, but pay attention to each of the steps below. Look at the example code carefully and make sure you understand what each bit is doing. In the next part we will build on this.

Step 1: Group together using a list { } the two primitives (Line and GeometricTransformation with Line) to rotate.
Step 2: Put Rotate[...] around this list. After the list, inside the end bracket ] for Rotate, indicate the angle of rotation. For example, use Pi/3. (Don’t forget the comma.)
Step 3: Also, after the angle, indicate the point about which the rotation will occur. In this example, {0,0}. Note that if no point of rotation is indicated, the collection of objects rotates about its own center. Here we want the rotation to occur about the origin.

Notice that the points are not rotated. This is fine. The lines should look like they are reflected across a mirror at angle Pi/3.

ptlist=RandomReal[{0,10},{5,2}];
Graphics[{
Rotate[{Line[ptlist],
GeometricTransformation[Line[ptlist],ReflectionTransform[{0,1}]]
},Pi/3,{0,0}],
Point[ptlist]
},PlotRange->14,Axes->True]

Review of Table

Recall that Table allows us to repeat a process and follow a pattern.

Table[n^2,{n,0,10}]

Adding a value after the maximum of the domain will specify the increment by which to count. The default is to count by 1. Below has the same list, but using an increment of 2.

Table[n^2,{n,0,10,2}]

We are going to use Table around Rotate to repeat the rotation for six angles. Fundamentally, the following table shows how this will work. (Note: “th” represents the angle θ “theta” of rotation.)

I like to think of this as “theta goes from 0 to 5π/3 counting by π/3.”

Table[th,{th,0,5Pi/3,Pi/3}]

If you don’t understand radians (you should!), this is the same as the following example.

Table[th,{th,0 Degree,300 Degree,60Degree}]

Table of Rotate

This is where it all comes together. Again, read the directions carefully.

Return to our Graphics code above and/or make a new copy here.
Step 1: In front of Rotate, put Table[
Step 2: After the end bracket ] for Rotate, put a comma and {th,0,5Pi/3,Pi/3} followed by an end bracket ] for Table.
Step 3: Change the Pi/3 within the Rotate (from our simpler rotation example) to “th” (no quotes).

Make sure there is still a comma after the end bracket ] to Table before Point.

Each time you evaluate this you will see different snowflake designs because of the random points.

ptlist=RandomReal[{0,10},{5,2}];
Graphics[{
Table[Rotate[{Line[ptlist],
GeometricTransformation[Line[ptlist],ReflectionTransform[{0,1}]]
},th,{0,0}],{th,0,5Pi/3,Pi/3}],
Point[ptlist]
},PlotRange->14,Axes->True]

Let’s get rid of the axes. Change True to False for the Axes option at the end.

ptlist=RandomReal[{0,10},{5,2}];
Graphics[{
Table[Rotate[{Line[ptlist],
GeometricTransformation[Line[ptlist],ReflectionTransform[{0,1}]]
},th,{0,0}],{th,0,5Pi/3,Pi/3}],
Point[ptlist]
},PlotRange->14,Axes->False]

Manipulate

Introduction to Manipulate

Manipulate works like Table, however with Manipulate the variable will change continuously.

Table[x,{x,0,10}]

Note that the structure is the same below as for Table above. The slider is automatically generated with Manipulate.

Manipulate[x,{x,0,10}]

When given a two-dimensional domain, Manipulate generates a two-dimensional slider. Below, the point is allowed to travel within a rectangle with a minimum corner located at {-1,-1} and a maximum corner located at {1,1}.

Manipulate[pt,{pt,{-1,-1},{1,1}}]

Let’s Manipulate our Snowflake

Step 0: Delete ptlist=RandomReal[{0,10},{5,2}]; at the top.
Step 1: Type Manipulate[ in front of Graphics.
Step 2: Put an end bracket ] after the last end bracket ] for Graphics. You will see a red up arrow indicating the need to put in the controls for Manipulate.
Step 3: Type a comma , where the red arrow is and press “Enter” to create a new line for the code.
Step 4: Type the following after the comma, where the red arrow is:    {{ptlist,{{1,1},{5,5}}},{-10,-10},{10,10},Locator}
The “ptlist” is the name of the control and we are starting the list with {1,1} and {5,5} as the initial points in the list. The domain of the points in the ptlist is a rectangle with a minimum corner of {-10,-10} and a maximum corner of {10,10}. “Locator” makes the points in ptlist controls that are directly movable within the graphical output. These types of controls are called locators.

Note that each time this code is evaluated, the points start in the same location {1,1} and {5,5}. To see those are the actual points, you could change the Axes setting back to True.

Manipulate[
Graphics[{
Table[Rotate[{Line[ptlist],
GeometricTransformation[Line[ptlist],ReflectionTransform[{0,1}]]
},th,{0,0}],{th,0,5Pi/3,Pi/3}],
Point[ptlist]
},PlotRange->14,Axes->False],
{{ptlist,{{1,1},{5,5}}},{-10,-10},{10,10},Locator}
]

To have random points, change the ptlist initialization list from {{1,1},{5,5}} to RandomReal[{0,10},{5,2}].

Manipulate[
Graphics[{
Table[Rotate[{Line[ptlist],
GeometricTransformation[Line[ptlist],ReflectionTransform[{0,1}]]
},th,{0,0}],{th,0,5Pi/3,Pi/3}],
Point[ptlist]
},PlotRange->14,Axes->False],
{{ptlist,RandomReal[{0,10},{5,2}]},{-10,-10},{10,10},Locator}
]

Play!

Option: Hide Locator Icons

Within the ptlist control, after Locator, add the option Appearance->None. Now the points included in Graphics will indicate each Locator rather than the default crosshairs.

Manipulate[
Graphics[{
Table[Rotate[{Line[ptlist],
GeometricTransformation[Line[ptlist],ReflectionTransform[{0,1}]]
},th,{0,0}],{th,0,5Pi/3,Pi/3}],
Point[ptlist]
},PlotRange->14,Axes->False],
{{ptlist,RandomReal[{0,10},{5,2}]},{-10,-10},{10,10},Locator,Appearance->None}
]

To increase the size of the points, before the Point[ptlist] add the directive PointSize[Medium]. (You can also try Large, Small, Tiny, 0.02, or another number.) Add a list { } around this new directive and Point[ptlist].

Manipulate[
Graphics[{
Table[Rotate[{Line[ptlist],
GeometricTransformation[Line[ptlist],ReflectionTransform[{0,1}]]
},th,{0,0}],{th,0,5Pi/3,Pi/3}],
{PointSize[Medium],Point[ptlist]}
},PlotRange->14,Axes->False],
{{ptlist,RandomReal[{0,10},{5,2}]},{-10,-10},{10,10},Locator,Appearance->None}
]

Option: More or Less Locators

To change the number of locators, reduce the 5 to 3 within the ptlist initialization. Try changing it to 10.

Manipulate[
Graphics[{
Table[Rotate[{Line[ptlist],
GeometricTransformation[Line[ptlist],ReflectionTransform[{0,1}]]
},th,{0,0}],{th,0,5Pi/3,Pi/3}],
{PointSize[Medium],Point[ptlist]}
},PlotRange->14,Axes->False],
{{ptlist,RandomReal[{0,10},{3,2}]},{-10,-10},{10,10},Locator,Appearance->None}
]

Locator controls built with a list of points, like we have done here, can take an option that allows for additional locators to be easily created (or deleted). Within the control, add the option LocatorAutoCreate->True. Change the starting number of points back to 5.

Now, when using the Manipulate, hold down the Alt key while clicking in the region. In an empty space, Alt-click on Windows (or Command-click on Mac) will generate a new locator. Using Alt-click on an existing locator will delete it. (Note that Alt-click very close to an existing locator will also delete it.)

Manipulate[
Graphics[{
Table[Rotate[{Line[ptlist],
GeometricTransformation[Line[ptlist],ReflectionTransform[{0,1}]]
},th,{0,0}],{th,0,5Pi/3,Pi/3}],
{PointSize[Medium],Point[ptlist]}
},PlotRange->14,Axes->False],
{{ptlist,RandomReal[{0,10},{5,2}]},{-10,-10},{10,10},Locator,Appearance->None,LocatorAutoCreate->True}
]

Option: Colors

Let’s make it look more like a snowflake by adjusting the color.

First, change the background color by adding an option to the Graphics. Include this immediately after Axes->False and separate by a comma. Try Background->Red. Then use Lighter[Blue,0.4] instead of Red.

Manipulate[
Graphics[{
Table[Rotate[{Line[ptlist],
GeometricTransformation[Line[ptlist],ReflectionTransform[{0,1}]]
},th,{0,0}],{th,0,5Pi/3,Pi/3}],
{PointSize[Medium],Point[ptlist]}
},PlotRange->14,Axes->False,Background->Lighter[Blue,0.4]],
{{ptlist,RandomReal[{0,10},{5,2}]},{-10,-10},{10,10},Locator,Appearance->None,LocatorAutoCreate->True}
]

To make the snowflake white, before Table and within the primary list { } within Graphics, add the directives White and Thick separated by commas. I also recommend changing the point size to Large (because of the Thick lines).

Manipulate[
Graphics[{White,Thick,
Table[Rotate[{Line[ptlist],
GeometricTransformation[Line[ptlist],ReflectionTransform[{0,1}]]
},th,{0,0}],{th,0,5Pi/3,Pi/3}],
{PointSize[Large],Point[ptlist]}
},PlotRange->14,Axes->False,Background->Lighter[Blue,0.4]],
{{ptlist,RandomReal[{0,10},{5,2}]},{-10,-10},{10,10},Locator,Appearance->None,LocatorAutoCreate->True}
]

Option: Show Mirrors

Drawing the lines where the mirrors are gives it a more snowflake-like appearance. We only need to draw one line and include it in the rotation to draw all of the mirrors at once.

Within the Rotate list of primitives, add Line[{{0,0},{10,0}}]. This draws a line segment along the x-axis. Including it within the Rotate will make copies along with the other lines.

Manipulate[
Graphics[{White,Thick,
Table[Rotate[{
Line[{{0,0},{10,0}}],
Line[ptlist],
GeometricTransformation[Line[ptlist],ReflectionTransform[{0,1}]]
},th,{0,0}],{th,0,5Pi/3,Pi/3}],
{PointSize[Large],Point[ptlist]}
},PlotRange->14,Axes->False,Background->Lighter[Blue,0.4]],
{{ptlist,RandomReal[{0,10},{5,2}]},{-10,-10},{10,10},Locator,Appearance->None,LocatorAutoCreate->True}
]

Say we want to turn the mirror lines on and off. We can do this with a checkbox control and an If statement. The variable for a checkbox control has default values of True or False. A simple example is below.

Manipulate[mirrors,{mirrors,{True,False}}]

After the ptlist control (before the very last bracket ] for the Manipulate) add a comma and a new control {mirrors,{True,False}}. (Note: This will create the checkbox, but it will not affect the image.)

Manipulate[
Graphics[{White,Thick,
Table[Rotate[{
Line[{{0,0},{10,0}}],
Line[ptlist],
GeometricTransformation[Line[ptlist],ReflectionTransform[{0,1}]]
},th,{0,0}],{th,0,5Pi/3,Pi/3}],
{PointSize[Large],Point[ptlist]}
},PlotRange->14,Axes->False,Background->Lighter[Blue,0.4]],
{{ptlist,RandomReal[{0,10},{5,2}]},{-10,-10},{10,10},Locator,Appearance->None,LocatorAutoCreate->True},
{mirrors,{True,False}}
]

Use an If[...] statement around the Line for the mirrors. In an If statement, the first argument evaluates to True or False, the second argument is what happens if the value is True, and the third argument is what happens if the value is False. In this case the empty list { } has nothing drawn when the checkbox is unchecked.

Manipulate[
Graphics[{White,Thick,
Table[Rotate[{
If[mirrors,Line[{{0,0},{10,0}}],{}],
Line[ptlist],
GeometricTransformation[Line[ptlist],ReflectionTransform[{0,1}]]
},th,{0,0}],{th,0,5Pi/3,Pi/3}],
{PointSize[Large],Point[ptlist]}
},PlotRange->14,Axes->False,Background->Lighter[Blue,0.4]],
{{ptlist,RandomReal[{0,10},{5,2}]},{-10,-10},{10,10},Locator,Appearance->None,LocatorAutoCreate->True},
{mirrors,{True,False}}
]

Option: Hide Points

To create a checkbox that hides the points (so you only see the lines), create a new control (like for the mirrors above) and use another If statement. This time put the If around the list for the points.

Manipulate[
Graphics[{White,Thick,
Table[Rotate[{
If[mirrors,Line[{{0,0},{10,0}}],{}],
Line[ptlist],
GeometricTransformation[Line[ptlist],ReflectionTransform[{0,1}]]
},th,{0,0}],{th,0,5Pi/3,Pi/3}],
If[points,{PointSize[Large],Point[ptlist]},{}]
},PlotRange->14,Axes->False,Background->Lighter[Blue,0.4]],
{{ptlist,RandomReal[{0,10},{5,2}]},{-10,-10},{10,10},Locator,Appearance->None,LocatorAutoCreate->True},
{mirrors,{True,False}},
{points,{True,False}}
]

Use the option ControlPlacement within each checkbox control to move them to the left side of the Manipulate.

Manipulate[
Graphics[{White,Thick,
Table[Rotate[{
If[mirrors,Line[{{0,0},{10,0}}],{}],
Line[ptlist],
GeometricTransformation[Line[ptlist],ReflectionTransform[{0,1}]]
},th,{0,0}],{th,0,5Pi/3,Pi/3}],
If[points,{PointSize[Large],Point[ptlist]},{}]
},PlotRange->14,Axes->False,Background->Lighter[Blue,0.4]],
{{ptlist,RandomReal[{0,10},{5,2}]},{-10,-10},{10,10},Locator,Appearance->None,LocatorAutoCreate->True},
{mirrors,{True,False},ControlPlacement->Left},
{points,{True,False},ControlPlacement->Left}
]

Option: Adjust Background Color

How much lighter (or darker) a color is within the Lighter (or Darker) function is determined by a number between 0 and 1. A slider control is easy to generate for this.

Manipulate[color,{color,0,1}]

Step 1: Under the points control, add a control for color with domain from 0 to 1.
Step 2: Within the Background option, change the 0.4 inside of Lighter (after Blue) to color. This will have values that change according to the control.
Step 3: Change Lighter to Darker. (Try it with Lighter, but when the background is completely lightened, you cannot see the white lines. Darker will not have that problem.)

Manipulate[
Graphics[{White,Thick,
Table[Rotate[{
If[mirrors,Line[{{0,0},{10,0}}],{}],
Line[ptlist],
GeometricTransformation[Line[ptlist],ReflectionTransform[{0,1}]]
},th,{0,0}],{th,0,5Pi/3,Pi/3}],
If[points,{PointSize[Large],Point[ptlist]},{}]
},PlotRange->14,Axes->False,Background->Darker[Blue,color]],
{{ptlist,RandomReal[{0,10},{5,2}]},{-10,-10},{10,10},Locator,Appearance->None,LocatorAutoCreate->True},
{mirrors,{True,False},ControlPlacement->Left},
{points,{True,False},ControlPlacement->Left},
{color,0,1}
]

To allow for lighter and darker blue values, use Blend. A simple example of Blend with Manipulate is below. Think of the included list of colors as a number line. The first color is assigned to value 0 and the last is 1. All colors in between are equally spaced values between 0 and 1.

Manipulate[Blend[{Red,Yellow,Blue},val],{val,0,1}]

For our snowflake, change Darker (or Lighter) to Blend as below. The control color will now set the value of the Blend. No new control is needed.

Manipulate[
Graphics[{White,Thick,
Table[Rotate[{
If[mirrors,Line[{{0,0},{10,0}}],{}],
Line[ptlist],
GeometricTransformation[Line[ptlist],ReflectionTransform[{0,1}]]
},th,{0,0}],{th,0,5Pi/3,Pi/3}],
If[points,{PointSize[Large],Point[ptlist]},{}]
},PlotRange->14,Axes->False,Background->Blend[{White,Blue,Black},color]],
{{ptlist,RandomReal[{0,10},{5,2}]},{-10,-10},{10,10},Locator,Appearance->None,LocatorAutoCreate->True},
{mirrors,{True,False},ControlPlacement->Left},
{points,{True,False},ControlPlacement->Left},
{color,0,1}
]

It starts with a white background (color value 0), so let’s initialize color to be another value. Make a list { } around the control name color and put 0.3 after it within the list. This will now set the initial value of color to be 0.3.

Manipulate[
Graphics[{White,Thick,
Table[Rotate[{
If[mirrors,Line[{{0,0},{10,0}}],{}],
Line[ptlist],
GeometricTransformation[Line[ptlist],ReflectionTransform[{0,1}]]
},th,{0,0}],{th,0,5Pi/3,Pi/3}],
If[points,{PointSize[Large],Point[ptlist]},{}]
},PlotRange->14,Axes->False,Background->Blend[{White,Blue,Black},color]],
{{ptlist,RandomReal[{0,10},{5,2}]},{-10,-10},{10,10},Locator,Appearance->None,LocatorAutoCreate->True},
{mirrors,{True,False},ControlPlacement->Left},
{points,{True,False},ControlPlacement->Left},
{{color,0.3},0,1}
]

You could list colors other than Black and White. Or try listing more than three colors.

Abby Brown
www.abbymath.com
CT@TP: Computational Thinking at Torrey Pines High School
December 2017

Note: A version of this has been published on the Wolfram Demonstrations Project as “Snowflake Designs.” http://demonstrations.wolfram.com/SnowflakeDesigns