Skip to content

Instantly share code, notes, and snippets.

Created December 30, 2016 16:39
Show Gist options
  • Save anonymous/80a7f4a5395f51cded5bf85d1280acb3 to your computer and use it in GitHub Desktop.
Save anonymous/80a7f4a5395f51cded5bf85d1280acb3 to your computer and use it in GitHub Desktop.
Math Mondays: "snowflake" drawing app
/*
Snowflake 2.0a
Open-source "snowflake" drawing app with true vector output.
Click the "save" button to create a PDF document of your snowflake,
suitable for editing in Inkscape, Corel, Illustrator, or so forth.
Written by Windell H. Oskay, www.evilmadscientist.com
Trigonometry updated for values of sides other than 6 by Glen Whitney.
Copyright 2009, 2016, all rights reserved.
Distributed under the GPL 3.0.
Saves files named "snowflake-####.pdf" in the directory where this .pde file
resides.
*/
import processing.pdf.*;
int sides = 6;
void DrawVertex(float x,float y,float angle)
{ // Angle is in radians
vertex(x*cos(angle) + y*sin(angle), y*cos(angle) - x*sin(angle));
}
boolean ReflectMode = true;
int SidesMax = 99;
float StartTime, InitTime;
float CircStartTime;
float timeNow;
float LastActiveTime;
float xValues[];
float yValues[];
int SideLength;
color circleColor;
color circleStroke;
color bgColor;
color symColor;
color segmentColor;
int CircleDia;
int mtCircleDia;
boolean dragging;
int MovePoint;
boolean pointsActive;
boolean pointsActiveOld;
color emptyCircle;
PFont font_MB48;
PFont font_MB24;
boolean overCircle(int x, int y, int diameter)
{
float disX = x - mouseX;
float disY = y - mouseY;
if(sqrt(sq(disX) + sq(disY)) < diameter/2 ) {
return true;
}
else {
return false;
}
}
boolean overRect(int x, int y, int width, int height)
{
if (mouseX >= x && mouseX <= x+width && mouseY >= y && mouseY <= y+height)
return true;
else
return false;
}
void setup()
{
size(640, 640);
smooth();
xValues = new float[2];
yValues = new float[2];
bgColor = color(70, 70, 200);
background(bgColor);
StartTime = millis();
InitTime= millis();
LastActiveTime = StartTime;
dragging = false;
pointsActive = false;
symColor = 0;
segmentColor = 255;
CircleDia = 10;
circleColor = color(255, 128, 0);
mtCircleDia = 10;
emptyCircle = color(255,128,0,0);
SideLength = width*9/20;
// font_MB48 = loadFont("Miso-Bold-48.vlw");
// font_MB24 = loadFont("Miso-Bold-24.vlw");
// textFont( font_MB24, 20); // MISO Typeface from http://omkrets.se/typografi/
ClearShape();
stroke(255);
circleStroke = 255;
strokeWeight(1);
pushMatrix();
translate(width/2,height/2);
drawShape();
popMatrix();
}
void ClearShape() {
// This sets the initial shape and draws it on the screen,
// with a triangular section highlighted.
xValues = subset(xValues, 0, 2);
yValues = subset(yValues, 0, 2);
xValues[0] = 0;
yValues[0] = -SideLength;
xValues[1] = SideLength*sin(TWO_PI/sides)/2;
yValues[1] = -(1+cos(TWO_PI/sides))*SideLength/2;
pointsActive = true;
StartTime = millis();
}
void mousePressed() {
int i,len,xt,yt;
len = xValues.length;
dragging = false;
i = 0;
while (i < len)
{
if (overCircle((int) xValues[i] + width/2, (int) yValues[i] + height/2, CircleDia))
{
dragging = true;
MovePoint = i;
i = len; // break
}
i++;
}
if ( dragging == false)
{
i = 0;
while (( i + 1) < len)
{
xt = (int) (xValues[i] + xValues[i+1] )/2;
yt = (int) (yValues[i] + yValues[i+1] )/2;
if (overCircle (xt + width/2, yt+ height/2, CircleDia))
{
dragging = true;
MovePoint = i+1;
xValues = splice(xValues, xt, i+1);
yValues = splice(yValues, yt, i+1);
i = len; // break
}
i++;
}
}
if (overRect(525, 610, 40, 25)) // Clear
{
ClearShape();
}
if (overRect(575, 610, 40, 25) ) // Save
{
beginRecord(PDF, "snowflake-####.pdf");
pushMatrix();
translate(width/2,height/2);
background(255);
stroke(0);
strokeWeight(1);
drawShape();
popMatrix();
endRecord();
strokeWeight(0);
stroke(255);
}
}
void mouseReleased() {
dragging = false;
}
void drawShape()
{
float angle;
int i,j;
fill(symColor);
beginShape(POLYGON);
i = 0;
while (i < sides)
{
angle = -i*TWO_PI/sides;
if (ReflectMode){
xValues = reverse(xValues);
yValues = reverse(yValues);
j = 0;
while (j < xValues.length)
{
DrawVertex(-1*xValues[j],yValues[j],angle);
j++;
}
xValues = reverse(xValues);
yValues = reverse(yValues);
j = 0;
while (j < xValues.length)
{
DrawVertex(xValues[j],yValues[j],angle);
j++;
}
i++;
}
else {
j = 0;
while (j < xValues.length)
{
DrawVertex(xValues[j],yValues[j],angle);
j++;
}
i++;
}
}
endShape(CLOSE);
}
void draw()
{
int i,j,len,xt,yt;
float xf,yf;
float TimeTemp;
len = xValues.length;
timeNow = millis();
if (pointsActive)
LastActiveTime = timeNow;
if ((timeNow - LastActiveTime) < 5000)
pointsActiveOld = true;
else
pointsActiveOld = false;
pointsActive = false;
pushMatrix();
translate(width/2,height/2);
background(bgColor);
stroke(255);
strokeWeight(1);
drawShape();
popMatrix();
if ((timeNow - CircStartTime) < 2550)
{
j = (int) (timeNow - CircStartTime) / 10;
circleStroke = color(255,255,255,255-j);
}
if ((timeNow - StartTime) < 9525)// 6350
{
j = (int) (timeNow - StartTime) / 25;
if (j < 176)
{
symColor = color(255,255,255,j);
CircStartTime = timeNow;
}
else
{
symColor = color(255,255,255,176);
}
if (j <= 255)
segmentColor = color(255,255,255,255-j);
else
segmentColor = color(255,255,255,0);
fill(segmentColor);
strokeWeight(0);
stroke(segmentColor);
pushMatrix();
translate(width/2,height/2);
beginShape(POLYGON);
DrawVertex(0,0,0);
i = 0;
while (i < xValues.length)
{
DrawVertex(xValues[i],yValues[i],0);
i++;
}
DrawVertex(0,0,0);
endShape(CLOSE);
popMatrix();
strokeWeight(1);
stroke(circleStroke);
i = 0;
while (i < len)
{
{
pushMatrix();
translate(width/2,height/2);
fill(red(circleColor),green(circleColor),blue(circleColor),255-j);
ellipse(xValues[i], yValues[i], CircleDia, CircleDia);
popMatrix();
}
if (( i + 1) < len)
{
xt = (int) (xValues[i] + xValues[i+1] )/2;
yt = (int) (yValues[i] + yValues[i+1] )/2;
{
pushMatrix();
translate(width/2,height/2);
ellipse(xt, yt,CircleDia, CircleDia);
popMatrix();
}
}
i++;
}
}
else
{
symColor = color(255,255,255,176);
segmentColor = symColor;
}
strokeWeight(1);
stroke(255);
if ( dragging)
{
pointsActive = true;
CircStartTime = timeNow;
if (MovePoint == 0)
{
xt = width/2;
if (mouseY < height/2)
{
yValues[MovePoint] = mouseY - height/2;
yt = mouseY;
}
else
{
yValues[MovePoint] = 0;
yt = height/2;
}
}
else if (MovePoint == len -1) // Last point in array.
{
xf = mouseX - width/2;
yf = mouseY - height/2;
xf = -yf*tan(PI/sides);
if (yf > 0)
{
xf = 0;
yf = 0;
}
xValues[MovePoint] = (int) xf;
yValues[MovePoint] = (int) yf;
xt = (int) ( width/2 + xf);
yt = (int) ( height/2 + yf);
}
else
{
xValues[MovePoint] = mouseX - width/2;
yValues[MovePoint] = mouseY - height/2;
xt = mouseX;
yt = mouseY;
}
fill(circleColor);
ellipse(xt, yt,CircleDia, CircleDia);
}
else
{
i = 0;
while (i < len)
{
if (overCircle((int) xValues[i] + width/2, (int) yValues[i] + height/2, CircleDia))
{
pointsActive=true;
CircStartTime = timeNow;
pushMatrix();
translate(width/2,height/2);
fill(circleColor);
stroke(circleStroke);
ellipse(xValues[i], yValues[i], CircleDia, CircleDia);
popMatrix();
}
else if (pointsActiveOld)
{
pushMatrix();
translate(width/2,height/2);
fill(emptyCircle);
stroke(circleStroke);
ellipse(xValues[i], yValues[i], mtCircleDia, mtCircleDia);
popMatrix();
}
if (( i + 1) < len)
{
xt = (int) (xValues[i] + xValues[i+1] )/2;
yt = (int) (yValues[i] + yValues[i+1] )/2;
if (overCircle (xt + width/2,yt+ height/2, CircleDia))
{
pointsActive=true;
CircStartTime = timeNow;
pushMatrix();
translate(width/2,height/2);
fill(circleColor);
ellipse(xt, yt,CircleDia, CircleDia);
popMatrix();
}
else if (pointsActiveOld)
{
pushMatrix();
stroke(circleStroke);
translate(width/2,height/2);
fill(emptyCircle);
ellipse(xt, yt,mtCircleDia, mtCircleDia);
popMatrix();
}
}
i++;
}
}
// Draw text:
fill(255,255,255,128);
text("Clear", 530, 630);
text("Save", 580, 630);
if (overRect(525, 610, 40, 25) )
{
CircStartTime = timeNow;
pointsActive=true;
//fill(circleColor);
//rect(525, 610, 40, 25);
fill(255);
text("Clear", 530, 630);
}
if (overRect(575, 610, 40, 25) )
{
CircStartTime = timeNow;
pointsActive=true;
//fill(circleColor);
//rect(575, 610, 40, 25);
fill(255);
text("Save", 580, 630);
}
if ((timeNow - InitTime) < 10540)// 6350
{
TimeTemp = (timeNow - InitTime);
if (TimeTemp > 8000)
j = (int) ((TimeTemp - 8000) / 20);
else
j = 0;
fill(255,255,255,128-j);
// textFont(font_MB48, 48);
text("Snowflake 2.0", 10, 40);
// text("SymmetriSketch", 176, 355);
// textFont( font_MB24, 20);
text("Evil Mad Scientist Laboratories", 425, 25);
text("www.evilmadscientist.com", 450, 42);
fill(255);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment