From 6aacb7fe56ccc8d5d8af3364d5591e625462125a Mon Sep 17 00:00:00 2001 From: ryancan Date: Mon, 8 Aug 2016 11:07:21 -0400 Subject: [PATCH 01/84] Box on a Ramp index file for the under development sim of a box on a ramp --- rampIndex.html | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 rampIndex.html diff --git a/rampIndex.html b/rampIndex.html new file mode 100644 index 0000000..e14719f --- /dev/null +++ b/rampIndex.html @@ -0,0 +1,50 @@ + + + + + + Box on a Ramp + + + + + + + + + + + + + + + + + + + + + + + +

Box on a Ramp

+

+ Instructions: TBD +

+

+ +

+
+ +
+ + From 94d43809b4ca0e2cfc978411784d763384de817d Mon Sep 17 00:00:00 2001 From: ryancan Date: Mon, 8 Aug 2016 11:11:17 -0400 Subject: [PATCH 02/84] Box on a Ramp Sketch This is the beginning of a new sim that is still heavily under development. The idea is to show a FBD of a box on a ramp with a slider to adjust the angle of the ramp and show the corresponding changes in components of the FBD. Currently there is an adjustable ramp and a box that follows accordingly. FBD to come soon --- rampSketch.js | 52 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 rampSketch.js diff --git a/rampSketch.js b/rampSketch.js new file mode 100644 index 0000000..24a737f --- /dev/null +++ b/rampSketch.js @@ -0,0 +1,52 @@ +var rampSlider; +var theta; +var thetaVal; +var rightCorner; +var apex; +var center; + +function setup(){ + createCanvas(700,500); + background('blue'); + + + + rampSlider = createSlider(-150,150,0); + rampSlider.position(100,550); + + thetaVal = atan((400-(250-rampSlider.value))/(500)); + theta = thetaVal + + rightCorner = new createVector(600,400); + apex = new createVector(100,250-rampSlider.value()); + + center = new createVector((apex.x+rightCorner.x)/2,(apex.y+rightCorner.y)/2); + +} + +function draw(){ + background('blue'); + rectMode(CORNER); + fill('green'); + rect(0,400,700,100); //just some scenic grass + + rightCorner = new createVector(600,400); + apex = new createVector(100,250-rampSlider.value()); + center = new createVector((apex.x+rightCorner.x)/2,(apex.y+rightCorner.y)/2); + + theta = atan((rightCorner.y-apex.y)/(rightCorner.x-apex.x)); + + + fill('tan'); + triangle(100,400,apex.x,apex.y,rightCorner.x,rightCorner.y); + + fill('white'); + text("Angle = "+theta+" radians",450,450); + + rectMode(CENTER); + fill('brown'); + translate(center.x,center.y);//translates coordinate to center so box rotates correctly + rotate(theta); + rect(0,-40,80,80);//(0,0) is new position of center + +} From 71544276072a5b234d6439b00e9bb39fb3fe4f9e Mon Sep 17 00:00:00 2001 From: ryancan Date: Tue, 23 Aug 2016 10:18:25 -0400 Subject: [PATCH 03/84] Create sketch.js This is an updated version of a box on a ramp. The FBD is still not developed for this sim yet; currently exploring using either the Arrow() function of fbd() function from science.js. The ramp now has a slider to adjust the angle and output the corresponding value to user. There is also now a box on the ramp that obeys gravity and friction (to an extent...) when the angle of ramp is changed. The box will start to slide down the ramp at higher angles, but it will slide uninhibited by kinetic friction (which will change soon...). --- rampFBD/sketch.js | 133 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 rampFBD/sketch.js diff --git a/rampFBD/sketch.js b/rampFBD/sketch.js new file mode 100644 index 0000000..5531ffe --- /dev/null +++ b/rampFBD/sketch.js @@ -0,0 +1,133 @@ +var rampSlider; +var theta; +var thetaVal; +var m; +var g; +var boxAccl; +var boxVel; +var boxPos; +var reset; +var mu; +var friction; +var rampGrav; + + +function setup(){ + createCanvas(700,500); + background('blue'); + + m = 5;//mass of block + g = 0.0981;//gravity + mu = .3;//coefficient of static friction + + //slider used to add/subtract y-value to apex of triangle, thus changing the angle of ramp + rampSlider = createSlider(-150,150,0); + rampSlider.position(100,550); + + //calculate angle of ramp + theta = atan((400-(250-rampSlider.value))/(500)); + + //setup ramp triangular coordinates using vectors + rightCorner = new createVector(600,400); + apex = new createVector(100,250-rampSlider.value()); + + //calculate middle of incline as vector so that those coordinates can be used to draw the box + center = new createVector((apex.x+rightCorner.x)/2,(apex.y+rightCorner.y)/2); + + boxAccl = new createVector(0,0); + boxVel = 0; + boxPos = 0; + +// gravVec = new Arrow(center,p5.Vector.add(center,boxAccl)); +// gravVec.color="purple"; +// gravVec.grab = false; +// gravVec.draggable = false; +// gravVec.showComponents = false; + + //trying to use science lib fbd on box +// box_fbd = new FBD(center,4,true); + + reset = createButton('reset'); + reset.position(200,200); + reset.mousePressed(reset2); +} + +//resets the box to middle of ramp and gives it 0 velocity and acceleration +reset2 = function(){ + boxPos=0; + boxVel=0; + boxAccl = new createVector(0,0); +} + +function draw(){ + background('blue'); + strokeWeight(1); + rectMode(CORNER); + fill('green'); + rect(0,400,700,100); //just some scenic grass + + //coordinates again of triangle ramp and box location + rightCorner = new createVector(600,400); + apex = new createVector(100,250-rampSlider.value()); + center = new createVector((apex.x+rightCorner.x)/2,(apex.y+rightCorner.y)/2); + + //recalculate angle in case ramp geometry has changed + theta = atan((rightCorner.y-apex.y)/(rightCorner.x-apex.x)); + + + friction = m*mu*g*cos(theta); + rampGrav = m*g*sin(theta); + + if (friction > rampGrav){ + friction = rampGrav; + }; + + boxAccl = new createVector(0,(rampGrav-friction)/m); + //vector was not used for velocity here because the box only moves uni-directionly along ramp + //this however should be changed and vectors should be used..... + boxVel = boxVel + boxAccl.y; + boxPos = boxPos + boxVel; + + //draw the ramp + fill('tan'); + triangle(100,400,apex.x,apex.y,rightCorner.x,rightCorner.y); + + //angle text output + //how to limit sig figs ??? + fill('white'); + text("Angle = "+theta+" degrees",450,450); + + rectMode(CENTER); + fill('brown'); + translate(center.x,center.y);//translates coordinate to center so box rotates correctly + rotate(theta);//rotate box to be flush with ramp according to angle theta + rect(boxPos,-40,80,80);//(0,0) is new position of center + stroke('black'); + strokeWeight(15); + //draw a stop for the box to prevent any weird transitions of box moving from ramp to ground + line(250,0,250,-40); + + //stops the box from moving when it reaches the stop + if(boxPos > 200){ + boxPos=205; + boxVel = 0; + boxAccl = 0; + }; + + angleMode(DEGREES); + +// box_fbd.mag = [550*g,friction,rampGrav,friction/mu]; +// box_fbd.direction = [90,180+theta,-1*theta,theta]; +// box_fbd.xoffsets = [0,0,0,0]; +// box_fbd.yoffsets = [0,0,0,0]; +// box_fbd.labels = ['force 1','force 2','force 3','force 4']; + + //fill('red'); +// box_fbd.update(); +// box_fbd.display(); + + //gravVec.target = p5.Vector.add(center,p5.Vector.mult(g,1000)); +// gravVec.update(); +// gravVec.display(); + +} From 8510a5b0dda1e0dd30d069e79162ec57006355ce Mon Sep 17 00:00:00 2001 From: ryancan Date: Tue, 23 Aug 2016 10:19:14 -0400 Subject: [PATCH 04/84] Create index.html index file for the box on a ramp fbd --- rampFBD/index.html | 52 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 rampFBD/index.html diff --git a/rampFBD/index.html b/rampFBD/index.html new file mode 100644 index 0000000..83b099a --- /dev/null +++ b/rampFBD/index.html @@ -0,0 +1,52 @@ + + + + + + Box on a Ramp + + + + + + + + + + + + + + + + + + + + + + + + + +

Box on a Ramp

+

+ Instructions: TBD +

+

+ +

+
+ +
+ + From 2ccc21023942d8c29eac122f04737b2ed3966f22 Mon Sep 17 00:00:00 2001 From: ryancan Date: Tue, 23 Aug 2016 10:19:32 -0400 Subject: [PATCH 05/84] Delete rampIndex.html --- rampIndex.html | 50 -------------------------------------------------- 1 file changed, 50 deletions(-) delete mode 100644 rampIndex.html diff --git a/rampIndex.html b/rampIndex.html deleted file mode 100644 index e14719f..0000000 --- a/rampIndex.html +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - Box on a Ramp - - - - - - - - - - - - - - - - - - - - - - - -

Box on a Ramp

-

- Instructions: TBD -

-

- -

-
- -
- - From 9fd4c39065c95151b2881b4859bb22c9cfebe07c Mon Sep 17 00:00:00 2001 From: ryancan Date: Tue, 23 Aug 2016 10:19:39 -0400 Subject: [PATCH 06/84] Delete rampSketch.js --- rampSketch.js | 52 --------------------------------------------------- 1 file changed, 52 deletions(-) delete mode 100644 rampSketch.js diff --git a/rampSketch.js b/rampSketch.js deleted file mode 100644 index 24a737f..0000000 --- a/rampSketch.js +++ /dev/null @@ -1,52 +0,0 @@ -var rampSlider; -var theta; -var thetaVal; -var rightCorner; -var apex; -var center; - -function setup(){ - createCanvas(700,500); - background('blue'); - - - - rampSlider = createSlider(-150,150,0); - rampSlider.position(100,550); - - thetaVal = atan((400-(250-rampSlider.value))/(500)); - theta = thetaVal - - rightCorner = new createVector(600,400); - apex = new createVector(100,250-rampSlider.value()); - - center = new createVector((apex.x+rightCorner.x)/2,(apex.y+rightCorner.y)/2); - -} - -function draw(){ - background('blue'); - rectMode(CORNER); - fill('green'); - rect(0,400,700,100); //just some scenic grass - - rightCorner = new createVector(600,400); - apex = new createVector(100,250-rampSlider.value()); - center = new createVector((apex.x+rightCorner.x)/2,(apex.y+rightCorner.y)/2); - - theta = atan((rightCorner.y-apex.y)/(rightCorner.x-apex.x)); - - - fill('tan'); - triangle(100,400,apex.x,apex.y,rightCorner.x,rightCorner.y); - - fill('white'); - text("Angle = "+theta+" radians",450,450); - - rectMode(CENTER); - fill('brown'); - translate(center.x,center.y);//translates coordinate to center so box rotates correctly - rotate(theta); - rect(0,-40,80,80);//(0,0) is new position of center - -} From 1689defbcff2a18ead241ad3b356211654990031 Mon Sep 17 00:00:00 2001 From: ryancan Date: Tue, 23 Aug 2016 10:20:24 -0400 Subject: [PATCH 07/84] Create index.html --- terminal-velocity/index.html | 1 + 1 file changed, 1 insertion(+) create mode 100644 terminal-velocity/index.html diff --git a/terminal-velocity/index.html b/terminal-velocity/index.html new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/terminal-velocity/index.html @@ -0,0 +1 @@ + From 517f8cb73f597d191d7b83f145b74a2d8c44340f Mon Sep 17 00:00:00 2001 From: ryancan Date: Tue, 23 Aug 2016 10:21:02 -0400 Subject: [PATCH 08/84] Update index.html index file for terminal velocity sketch --- terminal-velocity/index.html | 55 ++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/terminal-velocity/index.html b/terminal-velocity/index.html index 8b13789..79dbf76 100644 --- a/terminal-velocity/index.html +++ b/terminal-velocity/index.html @@ -1 +1,56 @@ + + + + + + Terminal Velocity + + + + + + + + + + + + + + + + + + + + + + + +

Terminal Velocity

+

+ Instructions: The particle freefalls from rest and eventually reaches terminal velocity. +

+

+ Red arrow is weight vector. + Blue arrow is drag force vector. + Green arrow is velocity vector. + Purple arrow is net force vector. +

+
+ +
+ + From 1ab786def1e34ee2b8dcd160c9faae1a6b1d9cde Mon Sep 17 00:00:00 2001 From: ryancan Date: Tue, 23 Aug 2016 10:22:49 -0400 Subject: [PATCH 09/84] Create sketch.js --- terminal-velocity/sketch.js | 133 ++++++++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 terminal-velocity/sketch.js diff --git a/terminal-velocity/sketch.js b/terminal-velocity/sketch.js new file mode 100644 index 0000000..a09d62b --- /dev/null +++ b/terminal-velocity/sketch.js @@ -0,0 +1,133 @@ +//note --- the webpage does not work when page is refreshed in browser + + +var mass; //mass +var g; //gravity +var rho; +var Cd; +var R; +var A;//frontal area +var start; +var equaiton; + +function setup() { + + canvas = createCanvas(800, 500); + canvas.parent('sketch-holder'); + + equation = loadImage("/drag_equation.jpeg") + + g = -9.81;//m/s2 + mass = createSlider(1,10,5);//kg + mass.position(50,330); + //massText = createDiv('Use this slider to change mass'); + //massText.position(350,800); + rho = createSlider(0,100,1.225); + rho.position(50,360);//kg/m3 + //rhoText = createDiv('Use this to change density of fluid medium'); + //rhoText.position(10,800); + Cd = .15;//dimensionless + R = createSlider(0.2,0.5,0.25,0.05);//m + R.position(50,390); + //Rtext = createDiv('Use this to change radius of sphere'); + //Rtext.position(200,200); + A = PI*(R.value()*R.value());//m2 - half the surface area of a sphere + + start = createButton('Click to start freefall'); + start.position(50,200); + start.mousePressed(run); + + velocity = createVector(0,0); + acceleration = createVector(0,0); + basePosition = createVector(width/2,height/2); + weight = createVector(0,-(mass.value()*g)); + drag = createVector(0,0); + + bg = new movingBackground('clouds',basePosition,velocity,acceleration); + + center = createVector((width/2)+150,height/2); + velVec = new Arrow(center,p5.Vector.add(center,bg.velocity)) + velVec.color="green"; + velVec.grab = false; + velVec.draggable = false; + velVec.showComponents = false; + + accelVec = new Arrow(center,p5.Vector.add(center,bg.acceleration)) + accelVec.color="purple"; + accelVec.grab = false; + accelVec.draggable = false; + accelVec.showComponents = false; + + dragVec = new Arrow(center,p5.Vector.add(center,drag)) + dragVec.color = "blue"; + dragVec.grab = false; + dragVec.draggable = false; + dragVec.showComponents = false; + + gravVec = new Arrow(center,p5.Vector.add(center,weight)) + gravVec.color = "red"; + gravVec.grab = false; + gravVec.draggable = false; + gravVec.showComponents = false; + + frameRate(30);//use to slow things down a bit + +noLoop(); +bg.acceleration = createVector(0,0); +} + +function draw() { + background('white'); + +//Limits the freefall velocity using net force(weight-drag) to acheive terminal velocity + + weight = createVector(0,-(mass.value()*g)); + A = PI*(R.value()*R.value());//m2 - half the surface area of a sphere + + drag.y = ((rho.value())*(Cd)*(A)*((bg.velocity.y)*(bg.velocity.y)))/2; //mimics real drag equation, scalar quantity + bg.acceleration = createVector(0,-(weight.y-drag.y)/mass.value());//accel must be negative to mimic falling in science lib + + + bg.update(); + bg.display(); + + rectMode(CORNER); + push(); + velVec.target = p5.Vector.add(center,p5.Vector.mult(bg.velocity,-2));//cloud vel positive, ball falling needs to be made negative + velVec.update(); + velVec.display(); + pop(); + dragVec.target = p5.Vector.add(center,p5.Vector.mult(drag,-1));//drag needs to be given direction + dragVec.update(); + dragVec.display(); + gravVec.target = p5.Vector.add(center,p5.Vector.mult(weight,1)); + gravVec.display(); + accelVec.target = p5.Vector.add(center,p5.Vector.mult(bg.acceleration,-1*mass.value()));//really force vector, multiplied by mass to be equivalent with weight vec at start of sim + accelVec.update(); + accelVec.display(); + fill('orange'); + ellipse(center.x,center.y,R.value()*100,R.value()*100);//scale size of ball to mass + + fill('white'); + rect(0,0,370,500); + + fill('orange'); + text("Mass: "+mass.value()+" kg",225,150); + text("Fluid Density: "+rho.value()+" kg/m^3",225,180); + text("Sphere Radius: "+R.value()+" m",225,210); + text("Frontal Area: "+A+" m^2",225,240); + +image(equation,100,400,10,10);//not showing up?? + + + + +console.log(weight.y) +console.log(bg.velocity.y) +console.log(bg.acceleration.y) +console.log(drag.y) +} +function run() { +loop(); +// bg.velocity = createVector(0+bg.acceleration.x,0+bg.acceleration.y); +} From fb453a36175d56b26d292947de94dfa16e7e98ba Mon Sep 17 00:00:00 2001 From: ryancan Date: Tue, 23 Aug 2016 10:23:01 -0400 Subject: [PATCH 10/84] Delete index.html --- index.html | 55 ------------------------------------------------------ 1 file changed, 55 deletions(-) delete mode 100644 index.html diff --git a/index.html b/index.html deleted file mode 100644 index cd3442b..0000000 --- a/index.html +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - Terminal Velocity - - - - - - - - - - - - - - - - - - - - - - - -

Terminal Velocity

-

- Instructions: The particle freefalls from rest and eventually reaches terminal velocity. -

-

- Red arrow is weight vector. - Blue arrow is drag force vector. - Green arrow is velocity vector. - Purple arrow is net force vector. -

-
- -
- - From 091e34b590a846ed13a0e623bd7eabc42b194e2c Mon Sep 17 00:00:00 2001 From: ryancan Date: Tue, 23 Aug 2016 10:23:17 -0400 Subject: [PATCH 11/84] Delete sketch.js --- sketch.js | 111 ------------------------------------------------------ 1 file changed, 111 deletions(-) delete mode 100644 sketch.js diff --git a/sketch.js b/sketch.js deleted file mode 100644 index e18d867..0000000 --- a/sketch.js +++ /dev/null @@ -1,111 +0,0 @@ -//note --- the webpage does not work when page is refreshed in browser - - -var mass; //mass -var g; //gravity -var rho; -var Cd; -var A; -var start; - -function setup() { - - canvas = createCanvas(500, 500); - canvas.parent('sketch-holder'); - - g = -9.81;//m/s2 - mass = createSlider(1,20,10);//kg - mass.position(350,750); - massText = createDiv('Use this slider to change mass'); - massText.position(350,800); - rho = createSlider(0,100,1.225); - rho.position(10,750);//kg/m3 - rhoText = createDiv('Use this to change density of fluid medium'); - rhoText.position(10,800); - Cd = .15;//dimensionless - A = 0.05;//m2 - - start = createButton('Click to start freefall'); - start.position(50,150); - start.mousePressed(run); - - velocity = createVector(0,0); - acceleration = createVector(0,0); - basePosition = createVector(width/2,height/2); - weight = createVector(0,-(mass.value()*g)); - drag = createVector(0,0); - - bg = new movingBackground('clouds',basePosition,velocity,acceleration); - - center = createVector(width/2,height/2); - velVec = new Arrow(center,p5.Vector.add(center,bg.velocity)) - velVec.color="green"; - velVec.grab = false; - velVec.draggable = false; - velVec.showComponents = false; - - accelVec = new Arrow(center,p5.Vector.add(center,bg.acceleration)) - accelVec.color="purple"; - accelVec.grab = false; - accelVec.draggable = false; - accelVec.showComponents = false; - - dragVec = new Arrow(center,p5.Vector.add(center,drag)) - dragVec.color = "blue"; - dragVec.grab = false; - dragVec.draggable = false; - dragVec.showComponents = false; - - gravVec = new Arrow(center,p5.Vector.add(center,weight)) - gravVec.color = "red"; - gravVec.grab = false; - gravVec.draggable = false; - gravVec.showComponents = false; - - frameRate(30);//use to slow things down a bit - - noLoop(); -} - -function draw() { - background('white'); - -//Limits the freefall velocity using net force(weight-drag) to acheive terminal velocity - - - weight = createVector(0,-(mass.value()*g)); - - drag.y = ((rho.value())*(Cd)*(A)*((bg.velocity.y)*(bg.velocity.y)))/2; //mimics real drag equation, scalar quantity - bg.acceleration = createVector(0,-(weight.y-drag.y)/mass.value());//accel must be negative to mimic falling in science lib - - - bg.update(); - bg.display(); - - rectMode(CORNER); - push(); - velVec.target = p5.Vector.add(center,p5.Vector.mult(bg.velocity,-1));//cloud vel positive, ball falling needs to be made negative - velVec.update(); - velVec.display(); - pop(); - dragVec.target = p5.Vector.add(center,p5.Vector.mult(drag,-1));//drag needs to be given direction - dragVec.update(); - dragVec.display(); - gravVec.target = p5.Vector.add(center,p5.Vector.mult(weight,1)); - gravVec.display(); - accelVec.target = p5.Vector.add(center,p5.Vector.mult(bg.acceleration,-1*mass.value()));//really force vector, multiplied by mass to be equivalent with weight vec at start of sim - accelVec.update(); - accelVec.display(); - fill('orange'); - ellipse(center.x,center.y,mass.value()*3,mass.value()*3);//scale size of ball to mass - - - -console.log(weight.y) -console.log(bg.velocity.y) -console.log(bg.acceleration.y) -console.log(drag.y) -} -function run() { - loop(); -} From 3e35ae14431d19c1831105af32ff69e50d935751 Mon Sep 17 00:00:00 2001 From: ryancan Date: Tue, 23 Aug 2016 10:25:15 -0400 Subject: [PATCH 12/84] Update README.md --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 1672a0f..0d90ce1 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,5 @@ # terminal_velocity A sim in development to simulate terminal velocity with the added bonus of interactive sliders to change mass of falling object and density of fluid. + +#Box on a Ramp FBD +A sim in development to demonstrate how a box behaves on an adjustable ramp. The goal is to have the Box FBD displayed and responsive to changes in the ramp angle. The box will also begin to slide down the ramp when gravitational forces overcome fricitonal forces. From 46f75656ca936cc0a218a2c5503919c4d8145284 Mon Sep 17 00:00:00 2001 From: ryancan Date: Mon, 5 Sep 2016 21:33:42 -0400 Subject: [PATCH 13/84] Update sketch.js --- rampFBD/sketch.js | 55 ++++++++++++++++++++++++----------------------- 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/rampFBD/sketch.js b/rampFBD/sketch.js index 5531ffe..038022f 100644 --- a/rampFBD/sketch.js +++ b/rampFBD/sketch.js @@ -1,16 +1,5 @@ -var rampSlider; -var theta; -var thetaVal; -var m; -var g; -var boxAccl; -var boxVel; -var boxPos; -var reset; -var mu; -var friction; -var rampGrav; +var center, weight; function setup(){ createCanvas(700,500); @@ -19,6 +8,7 @@ function setup(){ m = 5;//mass of block g = 0.0981;//gravity mu = .3;//coefficient of static friction + weight = new createVector(0,m*g*250); //slider used to add/subtract y-value to apex of triangle, thus changing the angle of ramp rampSlider = createSlider(-150,150,0); @@ -34,15 +24,20 @@ function setup(){ //calculate middle of incline as vector so that those coordinates can be used to draw the box center = new createVector((apex.x+rightCorner.x)/2,(apex.y+rightCorner.y)/2); - boxAccl = new createVector(0,0); + friction = m*mu*g*cos(theta); + rampGrav = m*g*sin(theta); + + //where x-dir is parallel to ramp and y-dir is normal to ramp + boxAccl = new createVector((rampGrav-friction)/m,0); boxVel = 0; boxPos = 0; -// gravVec = new Arrow(center,p5.Vector.add(center,boxAccl)); -// gravVec.color="purple"; -// gravVec.grab = false; -// gravVec.draggable = false; -// gravVec.showComponents = false; + gravEnd = p5.Vector.add(center,weight) + gravVec = new Arrow(center,gravEnd); + gravVec.color= color('red'); + gravVec.grab = false; + gravVec.draggable = false; + gravVec.showComponents = false; //trying to use science lib fbd on box // box_fbd = new FBD(center,4,true); @@ -60,12 +55,14 @@ reset2 = function(){ } function draw(){ + angleMode(DEGREES); background('blue'); strokeWeight(1); rectMode(CORNER); fill('green'); rect(0,400,700,100); //just some scenic grass + //coordinates again of triangle ramp and box location rightCorner = new createVector(600,400); apex = new createVector(100,250-rampSlider.value()); @@ -78,14 +75,16 @@ function draw(){ friction = m*mu*g*cos(theta); rampGrav = m*g*sin(theta); + //keeps box in equilibrium untill gravity overcomes friction if (friction > rampGrav){ friction = rampGrav; }; - boxAccl = new createVector(0,(rampGrav-friction)/m); + //where x-dir is parallel to ramp and y-dir is normal to ramp + boxAccl = new createVector((rampGrav-friction)/m,0); //vector was not used for velocity here because the box only moves uni-directionly along ramp //this however should be changed and vectors should be used..... - boxVel = boxVel + boxAccl.y; + boxVel = boxVel + boxAccl.x; boxPos = boxPos + boxVel; //draw the ramp @@ -95,7 +94,7 @@ function draw(){ //angle text output //how to limit sig figs ??? fill('white'); - text("Angle = "+theta+" degrees",450,450); + text("Angle of Ramp = "+theta.toFixed(2)+" degrees",400,450); rectMode(CENTER); fill('brown'); @@ -111,11 +110,9 @@ function draw(){ if(boxPos > 200){ boxPos=205; boxVel = 0; - boxAccl = 0; + boxAccl = new createVector(0,0); }; - angleMode(DEGREES); - // box_fbd.mag = [550*g,friction,rampGrav,friction/mu]; // box_fbd.direction = [90,180+theta,-1*theta,theta]; // box_fbd.xoffsets = [0,0,0,0]; @@ -126,8 +123,12 @@ function draw(){ // box_fbd.update(); // box_fbd.display(); - //gravVec.target = p5.Vector.add(center,p5.Vector.mult(g,1000)); -// gravVec.update(); -// gravVec.display(); +// gravVec.target = p5.Vector.add(center,p5.Vector.mult(weight,1)); + + gravVec.update(); + gravVec.display(); + console.log(weight) + console.log(gravVec.origin) + console.log(gravVec.target) } From fa131a8618cad6a939a7436853d65d56e22820b5 Mon Sep 17 00:00:00 2001 From: ryancan Date: Mon, 5 Sep 2016 21:34:22 -0400 Subject: [PATCH 14/84] Update sketch.js --- terminal-velocity/sketch.js | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/terminal-velocity/sketch.js b/terminal-velocity/sketch.js index a09d62b..d1ac3f2 100644 --- a/terminal-velocity/sketch.js +++ b/terminal-velocity/sketch.js @@ -15,14 +15,14 @@ function setup() { canvas = createCanvas(800, 500); canvas.parent('sketch-holder'); - equation = loadImage("/drag_equation.jpeg") + equation = loadImage("/drag_equation.jpeg"); g = -9.81;//m/s2 - mass = createSlider(1,10,5);//kg + mass = createSlider(1,25,5);//kg mass.position(50,330); //massText = createDiv('Use this slider to change mass'); //massText.position(350,800); - rho = createSlider(0,100,1.225); + rho = createSlider(1,30,1); rho.position(50,360);//kg/m3 //rhoText = createDiv('Use this to change density of fluid medium'); //rhoText.position(10,800); @@ -87,6 +87,9 @@ function draw() { drag.y = ((rho.value())*(Cd)*(A)*((bg.velocity.y)*(bg.velocity.y)))/2; //mimics real drag equation, scalar quantity bg.acceleration = createVector(0,-(weight.y-drag.y)/mass.value());//accel must be negative to mimic falling in science lib + if (abs(drag.y) > abs(weight.y)){ + drag.y = abs(weight.y); + } bg.update(); bg.display(); @@ -115,7 +118,9 @@ function draw() { text("Mass: "+mass.value()+" kg",225,150); text("Fluid Density: "+rho.value()+" kg/m^3",225,180); text("Sphere Radius: "+R.value()+" m",225,210); - text("Frontal Area: "+A+" m^2",225,240); + text("Frontal Area: "+A.toFixed(2)+" m^2",225,240); + + text("Velocity: "+bg.velocity.y.toFixed(2)+"m/s",150,300); image(equation,100,400,10,10);//not showing up?? @@ -129,5 +134,8 @@ console.log(drag.y) } function run() { loop(); +if (bg.velocity.y < 0){ + bg.velocity.y = 0; +} // bg.velocity = createVector(0+bg.acceleration.x,0+bg.acceleration.y); } From f5a9de411e49caf2ecf7ef4db9d141e0e8e153cb Mon Sep 17 00:00:00 2001 From: ryancan Date: Mon, 5 Sep 2016 21:55:07 -0400 Subject: [PATCH 15/84] Create index.html --- index.html | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 index.html diff --git a/index.html b/index.html new file mode 100644 index 0000000..63260a6 --- /dev/null +++ b/index.html @@ -0,0 +1,14 @@ + + + + Under Development Sims + + +

Sims currently being developed:

+ +

Box on a Ramp:

+ +

Terminal Velocity:

+ + + From b9f3f089246d233b1514b064b87bc48a2c43b5ef Mon Sep 17 00:00:00 2001 From: ryancan Date: Mon, 5 Sep 2016 21:57:04 -0400 Subject: [PATCH 16/84] Update index.html --- index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.html b/index.html index 63260a6..2f3c97c 100644 --- a/index.html +++ b/index.html @@ -6,7 +6,7 @@

Sims currently being developed:

-

Box on a Ramp:

+

Box on a Ramp:

Terminal Velocity:

From 7f87ba7c1e697ed768f071154ded7c3aa64ee203 Mon Sep 17 00:00:00 2001 From: ryancan Date: Mon, 5 Sep 2016 21:57:59 -0400 Subject: [PATCH 17/84] Update index.html --- index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.html b/index.html index 2f3c97c..53b1678 100644 --- a/index.html +++ b/index.html @@ -6,7 +6,7 @@

Sims currently being developed:

-

Box on a Ramp:

+

Box on a Ramp:

Terminal Velocity:

From bd8c437945347d737cde4f74b825c50de12ad057 Mon Sep 17 00:00:00 2001 From: ryancan Date: Mon, 5 Sep 2016 21:58:40 -0400 Subject: [PATCH 18/84] Update index.html --- index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.html b/index.html index 53b1678..49bbaec 100644 --- a/index.html +++ b/index.html @@ -8,7 +8,7 @@

Sims currently being developed:

Box on a Ramp:

-

Terminal Velocity:

+

Terminal Velocity:

From 26bd51ffc574a1d20377d942ef6d2341f6007b55 Mon Sep 17 00:00:00 2001 From: ryancan Date: Mon, 5 Sep 2016 21:59:21 -0400 Subject: [PATCH 19/84] Update index.html --- index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.html b/index.html index 49bbaec..e8036de 100644 --- a/index.html +++ b/index.html @@ -6,7 +6,7 @@

Sims currently being developed:

-

Box on a Ramp:

+

Box on a Ramp:

Terminal Velocity:

From 07aec5626902db59f2885c2bf5e953851ebb4f0e Mon Sep 17 00:00:00 2001 From: ryancan Date: Mon, 5 Sep 2016 21:59:56 -0400 Subject: [PATCH 20/84] Update index.html --- index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.html b/index.html index e8036de..49bbaec 100644 --- a/index.html +++ b/index.html @@ -6,7 +6,7 @@

Sims currently being developed:

-

Box on a Ramp:

+

Box on a Ramp:

Terminal Velocity:

From 277d7accb236a53ae75021b0cb2ed79e4db1fec3 Mon Sep 17 00:00:00 2001 From: ryancan Date: Mon, 5 Sep 2016 22:01:10 -0400 Subject: [PATCH 21/84] Create science.js --- lib/science.js | 831 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 831 insertions(+) create mode 100644 lib/science.js diff --git a/lib/science.js b/lib/science.js new file mode 100644 index 0000000..ef279aa --- /dev/null +++ b/lib/science.js @@ -0,0 +1,831 @@ +/*! science-sims - v0.1.0 - 2016-07-26 */ +/** +* Draws an arrow from one point to another. Useful for vector diagramming. +* @method Arrow +* @param {p5.Vector} origin_ A vector object describing the origin +* @param {p5.Vector} target_ A vector object describing the end point +*/ + + +var somethingIsDragging; + +function Arrow(origin_, target_){ + + this.origin = origin_.copy(); + this.target = target_.copy(); + + //control handles + this.grab = true; + this.draggable = true; + this.showComponents = false; + this.color = color('rgb(255,255,255)'); + this.selected = false; + this.dragSelected = false; + this.isDragging = false; + this.width = 20; + + + //mouse old coordinates for transalation + this.oldX = 0; + this.oldY = 0; + + + + +this.display = function(){ + + push(); + fill(this.color); + noStroke(); + //draw arrow + var d = dist(this.origin.x,this.origin.y, this.target.x,this.target.y); + var w = this.width; + translate(this.origin.x,this.origin.y); + var angle = angCalc(this); + + rotate(angle); + + //draw arrow + if(this.boundChk() && this.draggable==true){ + fill(red(this.color)+(255-red(this.color))/2,green(this.color)+(255-green(this.color))/2,blue(this.color)+(255-blue(this.color))/2); + + } + if(this.isDragging==true){ + fill(red(this.color)+(255-red(this.color))/2,green(this.color)+(255-green(this.color))/2,blue(this.color)+(255-blue(this.color))/2); + } + drawArrow(w,d,this); + pop();//reset drawing state + + //draw components if requested + if(this.showComponents === true){ + push(); + strokeWeight(2); + stroke(this.color); + textSize(18); + line(this.origin.x, this.origin.y, this.target.x, this.origin.y); + line(this.origin.x, this.origin.y, this.origin.x, this.target.y); + pop(); + push(); + fill(0); + text("y: " + (Math.round(-1*(this.target.y-this.origin.y))).toString(), this.origin.x, this.target.y); + text("x: " + (Math.round(this.target.x-this.origin.x)).toString(), this.target.x,this.origin.y); + pop(); + } + +}; +this.update = function(){ + if(this.selected){ + + this.target.x = mouseX; + this.target.y = mouseY; + } + else if(this.dragSelected){ + + if(this.oldX !== mouseX && this.oldX !== 0){ + + this.target.x += mouseX - this.oldX; + this.origin.x += mouseX - this.oldX; + } + + if(this.oldY !== mouseY && this.oldY !== 0){ + this.target.y += mouseY - this.oldY; + this.origin.y += mouseY - this.oldY; + } + + this.oldX = mouseX; + this.oldY = mouseY; + + } +}; + + +this.boundChk = function() { + + // get distance from the point to the two ends of the line +var d1 = dist(mouseX,mouseY, this.origin.x,this.origin.y); +var d2 = dist(mouseX,mouseY, this.target.x-2,this.target.y-2); + +// get the length of the line +var lineLen = dist(this.origin.x,this.origin.y, this.target.x-2,this.target.y-2); +buffer = 2; + +if (buffer === undefined){ buffer = 1; } // higher # = less accurate + +// if the two distances are equal to the line's length, the point is on the line! +// note we use the buffer here to give a range, rather than one # + +if (d1+d2 >= lineLen-buffer && d1+d2 <= lineLen+buffer) { + return true; +} +return false; +}; + +} + +function drawArrow(thickness,length,arrow){ + //draw the arrow itself + translate(0,-thickness/2); + // rect(0, thickness/4, length, thickness/2); + // triangle(length, 0, length, thickness, length+15, thickness/2); + rect(0, thickness/4, length-8, thickness/2); + triangle(length-8, 0, length-8, thickness, length+(thickness/2), thickness/2); + //draw handle + if(arrow.grab === true){ + var d = dist(arrow.target.x,arrow.target.y,mouseX,mouseY); + if(d < 6){ + fill(40,40); + strokeWeight(1); + stroke('black'); + ellipse(length,thickness/2, arrow.width*1.5,arrow.width*1.5); + if(mouseIsPressed){ + arrow.selected = true; + fill(255, 255, 0, 150); + arrow.isDragging = true; + } + else{ + arrow.selected = false; + arrow.isDragging = false; + fill(255,255,255,200); + } + + } + else{ + noFill(); + } + + //strokeWeight(2); + //stroke(arrow.color); + //ellipse(length,thickness/2, 12,12); + + //drag handle + if(arrow.draggable === true){ + + + if(arrow.boundChk()){ + if(mouseIsPressed){ + + arrow.dragSelected = true; + arrow.isDragging = true; + somethingIsDragging = true; + if(!arrow.isDragging){ + if(somethingIsDragging){ + arrow.oldX = arrow.oldX; + arrow.oldY = arrow.oldY; + } + } + else { + arrow.oldX = mouseX; + arrow.oldY = mouseY; + fill(255,255,0,100); + } + } + else{ + arrow.dragSelected = false; + arrow.isDragging = false; + somethingIsDragging = false; + fill(255,255,255,100); + this.oldX = 0; + this.oldY = 0; + } + + } + else{ + noFill(); + } + + + if(arrow.selected && arrow.dragSelected){ + arrow.dragSelected = false; + } + + } + } + + +} + + +function angCalc(arrow){ + //angleMode(DEGREES); + return atan2(arrow.target.y-arrow.origin.y,arrow.target.x-arrow.origin.x); +}; + +var Mover = function(position, velocity, acceleration, m, color){ + this.position = new createVector(position.x, position.y); + this.velocity = new createVector(velocity.x, velocity.y); + this.acceleration = new createVector(acceleration.x, acceleration.y); + this.limit = 20; + this.mass = m; + this.color = color; + this.size = this.mass; + this.outline = 255; + + this.tail = false; + this.tailA = []; + //sets up angular variables for rotations + this.angle = 0; + this.aVelocity = 0; + this.aAcceleration = 0; + + + +this.update = function(){ + if(this.tail === true){ + this.tailA.push(this.position.copy()); + } + + this.velocity.add(this.acceleration); + this.velocity.limit(this.limit); + this.position.add(this.velocity); + this.acceleration.mult(0); + + + var hCut = 70; + if(this.tailA.length > hCut){ + this.tailA = this.tailA.slice(-1 * hCut); + } + + //handles angular momentum + this.aVelocity += this.aAcceleration; + this.angle += this.aVelocity; +}; +this.display = function(){ + + fill(this.color); + stroke(this.outline); + ellipse(this.position.x,this.position.y,this.size,this.size); + + if(this.tail === true){ + fill(0,0,0,0); + for(var i = 0; i < this.tailA.length; i++){ + ellipse(this.tailA[i].x,this.tailA[i].y,4,4); + } + } +}; +this.applyForce = function(force){ + var f = force.get(); + f.div(this.mass); + this.acceleration.add(f); +}; +//Behaviors +this.wrapEdges = function() { + + if (this.position.x > width) { + this.position.x = 0; + } + else if (this.position.x < 0) { + this.position.x = width; + } + + if (this.position.y > height) { + this.position.y = 0; + } + else if (this.position.y < 0) { + this.position.y = height; + } +}; +this.bounceEdges = function(){ + if(this.position.x < 0+this.size/2){ + this.velocity.x *= -1; + this.position.x = 0+this.size/2; + + } + if(this.position.x > width-this.size/2){ + this.velocity.x *= -1; + this.position.x = width-this.size/2; + } + + if(this.position.y < 0+this.size/2){ + this.velocity.y *= -1; + this.position.y = 0+this.size/2; + + } + if(this.position.y > height-this.size/2){ + this.velocity.y *= -1; + this.position.y = height-this.size/2; + } +}; +this.towardMouse = function(a){ + var mouse = new Vector(mouseX,mouseY); + var dir = Vector.sub(mouse,this.position); + dir.normalize(); + dir.mult(a); + this.acceleration = dir; +}; + +} + + +Mover.prototype.get = function(){ + var bob = new Mover(this.position,this.velocity,this.acceleration); + return bob; +}; +Mover.get = function(m){ + var bob = new Mover(m.position, m.velocity, m.acceleration); + return bob; +}; + +/*spring*/ +function Spring(pos_, k_, m_, lengthOfSpring_, oscAmp_,mu_) { + boxsize = 70; + //no of coils (purely decorative, odd numbers work better) + this.noOfCoils = 11; + //how long is the equilibrium length of the spring, in px + this.lengthOfSpring = lengthOfSpring_; + //the transverse amplitude (also purely decorative) + this.transAmp = 15; + //time variables + this.tzero = millis(); + this.time = 0; + this.play = true; + //get the starting position of the spring. + this.xcent = pos_.x; + this.ycent = pos_.y; + //how do we want it? horizontal (theta = 0), vertical? (theta = PI/2) + this.rotation = 0; + //how big should the oscillation amplitude be? (as a fraction of the lengthOfSpring. i.e 0.5 means it will have an Amplitude equal to half the length of the spring, which is kinda long. 0.2 works good) + this.oscAmp = oscAmp_; + //calculate the frequency based on the spring constant k and the mass of the block m + //The second term in the sqrt accounts for the change in freq due to mu + this.freq = sqrt(k_/m_- sq(mu_)/(4*sq(m_))); + //friction coeff + this.mu = mu_; + //Mass + this.m = m_; + this.k = k_; + + + //some kinematics values + //where is equilibrium? + this.equilibrium = createVector(this.lengthOfSpring, 0); + //where is the mass? + this.displacement = createVector(0, 0); + //what is its velocity + this.velocity = createVector(0, 0); + //and its acceleration? + this.acceleration = createVector(0, 0); + + //Function used to toggle animation + this.setPlay = function(play_) { + this.play=play_; + } + + +this.update = function() { + //Keep track of time + if (this.play){ + //Animation is running so we update time + this.time = millis()/1000-this.tzero; + } + else { + //Animation pause "hold" time still + this.tzero = millis()/1000-this.time; + } +} + +this.display = function() { + + push(); + //Calculate argument for sin and amplitude + var theta = this.time * this.freq; + var amp = this.oscAmp * exp((-1*this.mu*this.time)/(2*this.m)); + + //Draw the mass at the end + translate(this.xcent, this.ycent); + rotate(this.rotation) + fill(200); + rect(this.lengthOfSpring - (boxsize / 2) + (this.lengthOfSpring - 60) * amp * sin(theta), -(boxsize / 2), boxsize, boxsize); + noFill(); + stroke(80); + strokeWeight(3); + + //Draw the spring + beginShape(); + //cosmetic start + curveVertex(-1, 0); + curveVertex(0, 0); + curveVertex(5, 0); + curveVertex(20, 0); + curveVertex(25, 0); + //this part makes the coil + for (var i = 0; i < this.lengthOfSpring - 60; i++) { + curveVertex(30 + (i * (1 + amp * sin(theta))), -this.transAmp * sin(2 * PI * this.noOfCoils * i / this.lengthOfSpring)); + } + //cosmetic end + curveVertex(30 + (i * (1 + amp * sin(theta))) + 5, 0); + curveVertex(30 + (i * (1 + amp * sin(theta))) + 20, 0); + curveVertex(30 + (i * (1 + amp * sin(theta))) + 25, 0); + curveVertex(30 + (i * (1 + amp * sin(theta))) + 30, 0); + curveVertex(30 + (i * (1 + amp * sin((theta)))) + 31, 0); + endShape(); + + //update the kinematic variables + this.displacement.x = this.equilibrium.x + ((this.lengthOfSpring-60) * amp * sin(theta)); + //TODO: Multiply Velocity and acceleration vals by actual Amplitude for final result + this.velocity.x = sqrt(this.k/this.m) * amp * cos(theta); + this.acceleration.x = -this.k/this.m * (amp * sin(theta)); + + pop(); +} +} + +function drawAxes(){ + line(width/2,0,width/2,height) + line(0,height/2,width,height/2) +} + +var movingBackground = function(whichKind_, position_, velocity_, acceleration_) { + maxHeight = 100; + this.velocity = velocity_; + this.position = position_; + this.acceleration = acceleration_; + this.whichKind = whichKind_; + this.shapes = []; + + if (this.whichKind == 'cityStreet') { + noOfBuildings = ((5 * width) / 70); + rectMode(CORNERS); + for (i = 0; i < noOfBuildings; i++) { + this.shapes.push(new backgroundShape(this.whichKind, this.velocity)) + this.shapes[i].position = createVector(-(width * 2) + (i * 70), this.position.y); + this.shapes[i].name = 'bldg ' + i; + this.shapes[i].layer = i; + this.shapes[i].scale = 3; + } + + } + + if (this.whichKind == 'clouds') { + noOfClouds = ((2 * width) / 10); + for (i = 0; i < noOfClouds; i++) { + this.shapes.push(new backgroundShape(this.whichKind, this.velocity)) + this.shapes[i].position = createVector(random(-width, 2 * width), random(-height, 2 * height)); + this.shapes[i].name = 'cloud ' + i; + this.shapes[i].layer = i; + this.shapes[i].scale = 2; + } + } + + this.l = this.shapes.length; + this.update = function() { + this.velocity.add(this.acceleration); + } + + this.display = function() { + for (i = this.l - 1; i >= 0; i--) { + this.shapes[i].run(); + } + } + +} + +var backgroundShape = function(whichKind_, velocity_) { + + this.howTall = random(40, maxHeight); + this.howWide = random(20, 100); + this.fill = random(60, 230); + + this.whichKind = whichKind_; + this.velocity = velocity_; + + + + + this.run = function() { + this.needsMoving() + this.update(); + + //only display the ones near the canvas + if (this.position.x < width + 100 && this.position.x > -100 && this.position.y > -100 && this.position.y < height + 100) { + this.display(); + } + }; + + this.update = function() { + + if (this.whichKind == 'cityStreet') { + rectMode(CORNERS); + this.position.add(this.velocity); + } + + if (this.whichKind == 'clouds') { + this.position.add(p5.Vector.mult(this.velocity, (noOfClouds - this.layer) / noOfClouds)); + } + + }; + + this.display = function() { + + if (this.whichKind == 'cityStreet') { + + push(); + fill(this.fill); + noStroke(); + rect(this.position.x, this.position.y, this.position.x + this.howWide, this.position.y - this.howTall); + //text(this.name,this.position.x,this.position.y+40) + pop(); + + push(); + stroke(0); + line(0, this.position.y, width, this.position.y); + pop(); + } + + if (this.whichKind == 'clouds') { + this.scale = 2; + push(); + fill(this.fill, 200); + noStroke(); + ellipse(this.position.x, this.position.y, this.howWide, this.howWide); + //text(this.name,this.position.x,this.position.y+40) + pop(); + } + + }; + + this.needsMoving = function() { + + if (this.position.x < -(width * (this.scale - 1))) { + this.position.x = width * this.scale; + } + if (this.position.x > (width * (this.scale))) { + this.position.x = -width * (this.scale - 1); + } + if (this.position.y < -(height * (this.scale - 1))) { + this.position.y = height * this.scale; + } + if (this.position.y > (height * this.scale)) { + this.position.y = -height * (this.scale - 1); + } + }; +}; + +//TODO: wheel object for rotating. +//TODO: make a smart rotate that rotates and moves along +//the ground at the correct (non-slipping) speed. +var wheel = function(_x,_y,_d){ + this.x = _x; //x position + this.y = _y; //y position + this.r = _d/2; //radius + this.d = _d; + this.arrowDecorations = []; + this.arrows = []; + this.rimColor = color('rgba(0,0,0,1)'); + this.spokeColor = color('rgba(0,0,0,1)'); + this.wheelColor = color('rgba(0,0,0,.1)'); + + //rotation variables + this.rotate = false; + this.ang = 0; + this.ang_speed = 1; + + //translation variables + this.trans_speed = 0; + + //decorations for wheel + this.vdecorate = false; + this.cdecorate = false; + + //arrow vectors to display(not implemented) + this.translation = false; + this.rotation = false; + this.rollingNoSlip = false; + + //actual arrow objects (only requires 3 to + //display all of the modes) + var orig = createVector(this.x,this.y); + var temp = createVector(this.x+this.r,this.y-this.r); + this.a1 = new Arrow(orig,temp); + this.a2 = new Arrow(orig,temp); + this.a3 = new Arrow(orig,temp); + + this.a1.width = 10; + this.a2.width = 10; + this.a3.width = 10; + + this.a1.color = color('green'); + this.a2.color = color('green'); + this.a3.color = color('green'); + + this.a1.draggable = false; + this.a1.grab = false; + this.a2.draggable = false; + this.a2.grab = false; + this.a3.draggable = false; + this.a3.grab = false; + //arrow display options + //-> static/relative + + + + + this.addDecorations = function(_decorations) { + + for(i=0;i= 360) this.ang = 0; + } + //draw the circles + fill(this.wheelColor); + stroke(this.rimColor); + strokeWeight(10); + ellipse(0,0,this.d,this.d); + //fill(color('rgba(200, 200, 200, .9)')); + //ellipse(0,0,this.d*0.85,this.d*0.85); + //fill(10); + //ellipse(0,0,this.d*0.05,this.d*0.05); + + //draw the spokes of the wheel + stroke(this.spokeColor); + strokeWeight(2); + for(var i = 0;i<16;i++){ + line(0,0, + (this.r-2)*cos(30*i), + (this.r-2)*sin(30*i)); + } + + //.............................. + // draw the decorations if any + //.............................. + +for(i=0;i Date: Mon, 5 Sep 2016 22:03:18 -0400 Subject: [PATCH 22/84] Update sketch.js --- terminal-velocity/sketch.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/terminal-velocity/sketch.js b/terminal-velocity/sketch.js index d1ac3f2..5840352 100644 --- a/terminal-velocity/sketch.js +++ b/terminal-velocity/sketch.js @@ -19,16 +19,16 @@ function setup() { g = -9.81;//m/s2 mass = createSlider(1,25,5);//kg - mass.position(50,330); + mass.position(50,300); //massText = createDiv('Use this slider to change mass'); //massText.position(350,800); rho = createSlider(1,30,1); - rho.position(50,360);//kg/m3 + rho.position(50,330);//kg/m3 //rhoText = createDiv('Use this to change density of fluid medium'); //rhoText.position(10,800); Cd = .15;//dimensionless R = createSlider(0.2,0.5,0.25,0.05);//m - R.position(50,390); + R.position(50,360); //Rtext = createDiv('Use this to change radius of sphere'); //Rtext.position(200,200); A = PI*(R.value()*R.value());//m2 - half the surface area of a sphere From 9c65b8a53cc76dc3e8a2f176b4b5a749908ef27a Mon Sep 17 00:00:00 2001 From: ryancan Date: Mon, 5 Sep 2016 22:06:09 -0400 Subject: [PATCH 23/84] Create p5.dom.js --- lib/p5.dom.js | 2106 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 2106 insertions(+) create mode 100644 lib/p5.dom.js diff --git a/lib/p5.dom.js b/lib/p5.dom.js new file mode 100644 index 0000000..7802515 --- /dev/null +++ b/lib/p5.dom.js @@ -0,0 +1,2106 @@ +/*! p5.dom.js v0.2.11 June 17, 2016 */ +/** + *

The web is much more than just canvas and p5.dom makes it easy to interact + * with other HTML5 objects, including text, hyperlink, image, input, video, + * audio, and webcam.

+ *

There is a set of creation methods, DOM manipulation methods, and + * an extended p5.Element that supports a range of HTML elements. See the + * + * beyond the canvas tutorial for a full overview of how this addon works. + * + *

Methods and properties shown in black are part of the p5.js core, items in + * blue are part of the p5.dom library. You will need to include an extra file + * in order to access the blue functions. See the + * using a library + * section for information on how to include this library. p5.dom comes with + * p5 complete or you can download the single file + * + * here.

+ *

See tutorial: beyond the canvas + * for more info on how to use this libary. + * + * @module p5.dom + * @submodule p5.dom + * @for p5.dom + * @main + */ + +(function (root, factory) { + if (typeof define === 'function' && define.amd) + define('p5.dom', ['p5'], function (p5) { (factory(p5));}); + else if (typeof exports === 'object') + factory(require('../p5')); + else + factory(root['p5']); +}(this, function (p5) { +// ============================================================================= +// p5 additions +// ============================================================================= + + /** + * Searches the page for an element with the given ID, class, or tag name (using the '#' or '.' + * prefixes to specify an ID or class respectively, and none for a tag) and returns it as + * a p5.Element. If a class or tag name is given with more than 1 element, + * only the first element will be returned. + * The DOM node itself can be accessed with .elt. + * Returns null if none found. You can also specify a container to search within. + * + * @method select + * @param {String} name id, class, or tag name of element to search for + * @param {String} [container] id, p5.Element, or HTML element to search within + * @return {Object/p5.Element|Null} p5.Element containing node found + * @example + *

+ * function setup() { + * createCanvas(100,100); + * //translates canvas 50px down + * select('canvas').position(100, 100); + * } + *
+ *
+ * // these are all valid calls to select() + * var a = select('#moo'); + * var b = select('#blah', '#myContainer'); + * var c = select('#foo', b); + * var d = document.getElementById('beep'); + * var e = select('p', d); + *
+ * + */ + p5.prototype.select = function (e, p) { + var res = null; + var container = getContainer(p); + if (e[0] === '.'){ + e = e.slice(1); + res = container.getElementsByClassName(e); + if (res.length) { + res = res[0]; + } else { + res = null; + } + }else if (e[0] === '#'){ + e = e.slice(1); + res = container.getElementById(e); + }else { + res = container.getElementsByTagName(e); + if (res.length) { + res = res[0]; + } else { + res = null; + } + } + if (res) { + return wrapElement(res); + } else { + return null; + } + }; + + /** + * Searches the page for elements with the given class or tag name (using the '.' prefix + * to specify a class and no prefix for a tag) and returns them as p5.Elements + * in an array. + * The DOM node itself can be accessed with .elt. + * Returns an empty array if none found. + * You can also specify a container to search within. + * + * @method selectAll + * @param {String} name class or tag name of elements to search for + * @param {String} [container] id, p5.Element, or HTML element to search within + * @return {Array} Array of p5.Elements containing nodes found + * @example + *
+ * function setup() { + * createButton('btn'); + * createButton('2nd btn'); + * createButton('3rd btn'); + * var buttons = selectAll('button'); + * + * for (var i = 0; i < buttons.length; i++){ + * buttons[i].size(100,100); + * } + * } + *
+ *
+ * // these are all valid calls to selectAll() + * var a = selectAll('.moo'); + * var b = selectAll('div'); + * var c = selectAll('button', '#myContainer'); + * var d = select('#container'); + * var e = selectAll('p', d); + * var f = document.getElementById('beep'); + * var g = select('.blah', f); + *
+ * + */ + p5.prototype.selectAll = function (e, p) { + var arr = []; + var res; + var container = getContainer(p); + if (e[0] === '.'){ + e = e.slice(1); + res = container.getElementsByClassName(e); + } else { + res = container.getElementsByTagName(e); + } + if (res) { + for (var j = 0; j < res.length; j++) { + var obj = wrapElement(res[j]); + arr.push(obj); + } + } + return arr; + }; + + /** + * Helper function for select and selectAll + */ + function getContainer(p) { + var container = document; + if (typeof p === 'string' && p[0] === '#'){ + p = p.slice(1); + container = document.getElementById(p) || document; + } else if (p instanceof p5.Element){ + container = p.elt; + } else if (p instanceof HTMLElement){ + container = p; + } + return container; + } + + /** + * Helper function for getElement and getElements. + */ + function wrapElement(elt) { + if(elt.tagName === "INPUT" && elt.type === "checkbox") { + var converted = new p5.Element(elt); + converted.checked = function(){ + if (arguments.length === 0){ + return this.elt.checked; + } else if(arguments[0]) { + this.elt.checked = true; + } else { + this.elt.checked = false; + } + return this; + }; + return converted; + } else if (elt.tagName === "VIDEO" || elt.tagName === "AUDIO") { + return new p5.MediaElement(elt); + } else { + return new p5.Element(elt); + } + } + + /** + * Removes all elements created by p5, except any canvas / graphics + * elements created by createCanvas or createGraphics. + * Event handlers are removed, and element is removed from the DOM. + * @method removeElements + * @example + *
+ * function setup() { + * createCanvas(100, 100); + * createDiv('this is some text'); + * createP('this is a paragraph'); + * } + * function mousePressed() { + * removeElements(); // this will remove the div and p, not canvas + * } + *
+ * + */ + p5.prototype.removeElements = function (e) { + for (var i=0; i + * var myDiv; + * function setup() { + * myDiv = createDiv('this is some text'); + * } + * + */ + + /** + * Creates a <p></p> element in the DOM with given inner HTML. Used + * for paragraph length text. + * Appends to the container node if one is specified, otherwise + * appends to body. + * + * @method createP + * @param {String} html inner HTML for element created + * @return {Object/p5.Element} pointer to p5.Element holding created node + * @example + *
+ * var myP; + * function setup() { + * myP = createP('this is some text'); + * } + *
+ */ + + /** + * Creates a <span></span> element in the DOM with given inner HTML. + * Appends to the container node if one is specified, otherwise + * appends to body. + * + * @method createSpan + * @param {String} html inner HTML for element created + * @return {Object/p5.Element} pointer to p5.Element holding created node + * @example + *
+ * var mySpan; + * function setup() { + * mySpan = createSpan('this is some text'); + * } + *
+ */ + var tags = ['div', 'p', 'span']; + tags.forEach(function(tag) { + var method = 'create' + tag.charAt(0).toUpperCase() + tag.slice(1); + p5.prototype[method] = function(html) { + var elt = document.createElement(tag); + elt.innerHTML = typeof html === undefined ? "" : html; + return addElement(elt, this); + } + }); + + /** + * Creates an <img /> element in the DOM with given src and + * alternate text. + * Appends to the container node if one is specified, otherwise + * appends to body. + * + * @method createImg + * @param {String} src src path or url for image + * @param {String} [alt] alternate text to be used if image does not load + * @param {Function} [successCallback] callback to be called once image data is loaded + * @return {Object/p5.Element} pointer to p5.Element holding created node + * @example + *
+ * var img; + * function setup() { + * img = createImg('http://p5js.org/img/asterisk-01.png'); + * } + *
+ */ + p5.prototype.createImg = function() { + var elt = document.createElement('img'); + var args = arguments; + var self; + var setAttrs = function(){ + self.width = elt.offsetWidth; + self.height = elt.offsetHeight; + if (args.length > 1 && typeof args[1] === 'function'){ + self.fn = args[1]; + self.fn(); + }else if (args.length > 1 && typeof args[2] === 'function'){ + self.fn = args[2]; + self.fn(); + } + }; + elt.src = args[0]; + if (args.length > 1 && typeof args[1] === 'string'){ + elt.alt = args[1]; + } + elt.onload = function(){ + setAttrs(); + } + self = addElement(elt, this); + return self; + }; + + /** + * Creates an <a></a> element in the DOM for including a hyperlink. + * Appends to the container node if one is specified, otherwise + * appends to body. + * + * @method createA + * @param {String} href url of page to link to + * @param {String} html inner html of link element to display + * @param {String} [target] target where new link should open, + * could be _blank, _self, _parent, _top. + * @return {Object/p5.Element} pointer to p5.Element holding created node + * @example + *
+ * var myLink; + * function setup() { + * myLink = createA('http://p5js.org/', 'this is a link'); + * } + *
+ */ + p5.prototype.createA = function(href, html, target) { + var elt = document.createElement('a'); + elt.href = href; + elt.innerHTML = html; + if (target) elt.target = target; + return addElement(elt, this); + }; + + /** INPUT **/ + + + /** + * Creates a slider <input></input> element in the DOM. + * Use .size() to set the display length of the slider. + * Appends to the container node if one is specified, otherwise + * appends to body. + * + * @method createSlider + * @param {Number} min minimum value of the slider + * @param {Number} max maximum value of the slider + * @param {Number} [value] default value of the slider + * @param {Number} [step] step size for each tick of the slider + * @return {Object/p5.Element} pointer to p5.Element holding created node + * @example + *
+ * var slider; + * function setup() { + * slider = createSlider(0, 255, 100); + * slider.position(10, 10); + * slider.style('width', '80px'); + * } + * + * function draw() { + * var val = slider.value(); + * background(val); + * } + *
+ * + *
+ * var slider; + * function setup() { + * colorMode(HSB); + * slider = createSlider(0, 360, 60, 40); + * slider.position(10, 10); + * slider.style('width', '80px'); + * } + * + * function draw() { + * var val = slider.value(); + * background(val, 100, 100, 1); + * } + *
+ */ + p5.prototype.createSlider = function(min, max, value, step) { + var elt = document.createElement('input'); + elt.type = 'range'; + elt.min = min; + elt.max = max; + if (step) elt.step = step; + if (typeof(value) === "number") elt.value = value; + return addElement(elt, this); + }; + + /** + * Creates a <button></button> element in the DOM. + * Use .size() to set the display size of the button. + * Use .mousePressed() to specify behavior on press. + * Appends to the container node if one is specified, otherwise + * appends to body. + * + * @method createButton + * @param {String} label label displayed on the button + * @param {String} [value] value of the button + * @return {Object/p5.Element} pointer to p5.Element holding created node + * @example + *
+ * var button; + * function setup() { + * createCanvas(100, 100); + * background(0); + * button = createButton('click me'); + * button.position(19, 19); + * button.mousePressed(changeBG); + * } + * + * function changeBG() { + * var val = random(255); + * background(val); + * } + *
+ */ + p5.prototype.createButton = function(label, value) { + var elt = document.createElement('button'); + elt.innerHTML = label; + elt.value = value; + if (value) elt.value = value; + return addElement(elt, this); + }; + + /** + * Creates a checkbox <input></input> element in the DOM. + * Calling .checked() on a checkbox returns if it is checked or not + * + * @method createCheckbox + * @param {String} [label] label displayed after checkbox + * @param {boolean} [value] value of the checkbox; checked is true, unchecked is false.Unchecked if no value given + * @return {Object/p5.Element} pointer to p5.Element holding created node + * @example + *
+ * var checkbox; + * + * function setup() { + * checkbox = createCheckbox('label', false); + * checkbox.changed(myCheckedEvent); + * } + * + * function myCheckedEvent() { + * if (this.checked()) { + * console.log("Checking!"); + * } else { + * console.log("Unchecking!"); + * } + * } + *
+ */ + p5.prototype.createCheckbox = function() { + var elt = document.createElement('div'); + var checkbox = document.createElement('input'); + checkbox.type = 'checkbox'; + elt.appendChild(checkbox); + //checkbox must be wrapped in p5.Element before label so that label appears after + var self = addElement(elt, this); + self.checked = function(){ + var cb = self.elt.getElementsByTagName('input')[0]; + if (cb) { + if (arguments.length === 0){ + return cb.checked; + }else if(arguments[0]){ + cb.checked = true; + }else{ + cb.checked = false; + } + } + return self; + }; + this.value = function(val){ + self.value = val; + return this; + }; + if (arguments[0]){ + var ran = Math.random().toString(36).slice(2); + var label = document.createElement('label'); + checkbox.setAttribute('id', ran); + label.htmlFor = ran; + self.value(arguments[0]); + label.appendChild(document.createTextNode(arguments[0])); + elt.appendChild(label); + } + if (arguments[1]){ + checkbox.checked = true; + } + return self; + }; + + /** + * Creates a dropdown menu <select></select> element in the DOM. + * @method createSelect + * @param {boolean} [multiple] [true if dropdown should support multiple selections] + * @return {Object/p5.Element} pointer to p5.Element holding created node + * @example + *
+ * var sel; + * + * function setup() { + * textAlign(CENTER); + * background(200); + * sel = createSelect(); + * sel.position(10, 10); + * sel.option('pear'); + * sel.option('kiwi'); + * sel.option('grape'); + * sel.changed(mySelectEvent); + * } + * + * function mySelectEvent() { + * var item = sel.value(); + * background(200); + * text("it's a "+item+"!", 50, 50); + * } + *
+ */ + p5.prototype.createSelect = function(mult) { + var elt = document.createElement('select'); + if (mult){ + elt.setAttribute('multiple', 'true'); + } + var self = addElement(elt, this); + self.option = function(name, value){ + var opt = document.createElement('option'); + opt.innerHTML = name; + if (arguments.length > 1) + opt.value = value; + else + opt.value = name; + elt.appendChild(opt); + }; + self.selected = function(value){ + var arr = []; + if (arguments.length > 0){ + for (var i = 0; i < this.elt.length; i++){ + if (value.toString() === this.elt[i].value){ + this.elt.selectedIndex = i; + } + } + return this; + }else{ + if (mult){ + for (var i = 0; i < this.elt.selectedOptions.length; i++){ + arr.push(this.elt.selectedOptions[i].value); + } + return arr; + }else{ + return this.elt.value; + } + } + }; + return self; + }; + + /** + * Creates a radio button <input></input> element in the DOM. + * The .option() method can be used to set options for the radio after it is + * created. The .value() method will return the currently selected option. + * + * @method createRadio + * @param {String} [divId] the id and name of the created div and input field respectively + * @return {Object/p5.Element} pointer to p5.Element holding created node + * @example + *
+ * var radio; + * + * function setup() { + * radio = createRadio(); + * radio.option("black"); + * radio.option("white"); + * radio.option("gray"); + * radio.style('width', '60px'); + * textAlign(CENTER); + * fill(255, 0, 0); + * } + * + * function draw() { + * var val = radio.value(); + * background(val); + * text(val, width/2, height/2); + * } + *
+ *
+ * var radio; + * + * function setup() { + * radio = createRadio(); + * radio.option('apple', 1); + * radio.option('bread', 2); + * radio.option('juice', 3); + * radio.style('width', '60px'); + * textAlign(CENTER); + * } + * + * function draw() { + * background(200); + * var val = radio.value(); + * if (val) { + * text('item cost is $'+val, width/2, height/2); + * } + * } + *
+ */ + p5.prototype.createRadio = function() { + var radios = document.querySelectorAll("input[type=radio]"); + var count = 0; + if(radios.length > 1){ + console.log(radios,radios[0].name); + var length = radios.length; + var prev=radios[0].name; + var current = radios[1].name; + count=1; + for(var i = 1; i < length; i++ ){ + current = radios[i].name; + if(prev != current){ + count++; + } + prev = current; + } + } + else if (radios.length == 1){ + count = 1; + } + var elt = document.createElement('div'); + var self = addElement(elt, this); + var times = -1; + self.option = function(name, value){ + var opt = document.createElement('input'); + opt.type = 'radio'; + opt.innerHTML = name; + if (arguments.length > 1) + opt.value = value; + else + opt.value = name; + opt.setAttribute('name',"defaultradio"+count); + elt.appendChild(opt); + if (name){ + times++; + var ran = Math.random().toString(36).slice(2); + var label = document.createElement('label'); + opt.setAttribute('id', "defaultradio"+count+"-"+times); + label.htmlFor = "defaultradio"+count+"-"+times; + label.appendChild(document.createTextNode(name)); + elt.appendChild(label); + } + return opt; + }; + self.selected = function(){ + var length = this.elt.childNodes.length; + if(arguments[0]) { + for (var i = 0; i < length; i+=2){ + if(this.elt.childNodes[i].value == arguments[0]) + this.elt.childNodes[i].checked = true; + } + return this; + } else { + for (var i = 0; i < length; i+=2){ + if(this.elt.childNodes[i].checked == true) + return this.elt.childNodes[i].value; + } + } + }; + self.value = function(){ + var length = this.elt.childNodes.length; + if(arguments[0]) { + for (var i = 0; i < length; i+=2){ + if(this.elt.childNodes[i].value == arguments[0]) + this.elt.childNodes[i].checked = true; + } + return this; + } else { + for (var i = 0; i < length; i+=2){ + if(this.elt.childNodes[i].checked == true) + return this.elt.childNodes[i].value; + } + return ""; + } + }; + return self + }; + + /** + * Creates an <input></input> element in the DOM for text input. + * Use .size() to set the display length of the box. + * Appends to the container node if one is specified, otherwise + * appends to body. + * + * @method createInput + * @param {Number} [value] default value of the input box + * @return {Object/p5.Element} pointer to p5.Element holding created node + * @example + *
+ * function setup(){ + * var inp = createInput(''); + * inp.input(myInputEvent); + * } + * + * function myInputEvent(){ + * console.log('you are typing: ', this.value()); + * } + * + *
+ */ + p5.prototype.createInput = function(value) { + var elt = document.createElement('input'); + elt.type = 'text'; + if (value) elt.value = value; + return addElement(elt, this); + }; + + /** + * Creates an <input></input> element in the DOM of type 'file'. + * This allows users to select local files for use in a sketch. + * + * @method createFileInput + * @param {Function} [callback] callback function for when a file loaded + * @param {String} [multiple] optional to allow multiple files selected + * @return {Object/p5.Element} pointer to p5.Element holding created DOM element + */ + p5.prototype.createFileInput = function(callback, multiple) { + + // Is the file stuff supported? + if (window.File && window.FileReader && window.FileList && window.Blob) { + // Yup, we're ok and make an input file selector + var elt = document.createElement('input'); + elt.type = 'file'; + + // If we get a second argument that evaluates to true + // then we are looking for multiple files + if (multiple) { + // Anything gets the job done + elt.multiple = 'multiple'; + } + + // Function to handle when a file is selected + // We're simplifying life and assuming that we always + // want to load every selected file + function handleFileSelect(evt) { + // These are the files + var files = evt.target.files; + // Load each one and trigger a callback + for (var i = 0; i < files.length; i++) { + var f = files[i]; + var reader = new FileReader(); + function makeLoader(theFile) { + // Making a p5.File object + var p5file = new p5.File(theFile); + return function(e) { + p5file.data = e.target.result; + callback(p5file); + }; + }; + reader.onload = makeLoader(f); + + // Text or data? + // This should likely be improved + if (f.type.indexOf('text') > -1) { + reader.readAsText(f); + } else { + reader.readAsDataURL(f); + } + } + } + + // Now let's handle when a file was selected + elt.addEventListener('change', handleFileSelect, false); + return addElement(elt, this); + } else { + console.log('The File APIs are not fully supported in this browser. Cannot create element.'); + } + }; + + + /** VIDEO STUFF **/ + + function createMedia(pInst, type, src, callback) { + var elt = document.createElement(type); + + // allow src to be empty + var src = src || ''; + if (typeof src === 'string') { + src = [src]; + } + for (var i=0; i