-
-
Save matt-morris/3bb507c785af53aa1215a067ae853af0 to your computer and use it in GitHub Desktop.
Math Mondays: "snowflake" drawing app
This file contains 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
/* | |
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