12. Processing and P5.js
https://processing.org/ https://gyazo.com/92902dcd7193e28f8cebfaf3c542108b
Sugar-coated Java + IDE
Good for simple visualiation
Easy to use
All Java features available
Camera, sound, etc.
http://gyazo.com/0b84019bb58c5c5e85572468793881ad.png
Movie created by Processing
http://gyazo.com/2226368693cdb1a77ca98fced5a96c87.png
Visualizing Data
by Ben Fry
https://www.amazon.co.jp/dp/4873113784 http://gyazo.com/93636cbe7792dc69db73035d15e8dc32.png https://www.amazon.co.jp/dp/0596514557 https://gyazo.com/dc96df72f3c580fd5d7e69cd858fc851
by Tanaka, Maekawa
http://gyazo.com/7b7a39436c6e83ac61d4f5d3f302a990.png
Let's start Processing
by Casey Reas, Ben Fry
http://gyazo.com/1057a6aae7a755267cc43c4141eb6787.png
https://www.amazon.co.jp/dp/4861008565 http://gyazo.com/8f12608e7f7b529520c07acc51fdb4f3.png https://gyazo.com/0e91dfb13f9dbf9c403cbc410ff96c04 https://www.amazon.co.jp/dp/1935182625
Very thick!
https://www.amazon.co.jp/dp/4861009502 http://gyazo.com/dc250960bfa3d5cc606a754b74c6c614.png https://gyazo.com/69cb44cc8355c120dfa19d2cdb058cf0 https://www.amazon.co.jp/dp/026202828X
Sharing Processing codes and ideas
https://gyazo.com/b6d9ab4384d962de6677f5cb9960e9aa
https://www.openprocessing.org/sketch/423314 https://gyazo.com/0f86aad2c6be7650ad8a4ceea95b5d7f
Getting Processing
Available on Windows, Mac, Linux
Drawing a line
line(0,0,100,100);
Click the play button to execute
(0, 0) at top-left
http://gyazo.com/64c3253194bc9688b5dfe08b49ddc756.png
Drawing a rectangle
rect(10,10,80,80);
http://gyazo.com/1a4f68fa1d2a7c5427285108fef07390.png
Drawing a circle
ellipse(50,50,30,30);
http://gyazo.com/8daf33a005334d2f43960d732060fcca.png
Using colors
Specify color before drawing
fill(#ffff00); など
Drawing characters
Prepare fonts
Tools⇒CreateFont
loadFont(); textFont(); text();
http://gyazo.com/9cdffe98a74776c405d3670551e6992e.png
Loops
for statement, if statement
...
Same syntax as C, Java
setup() and draw()
setup() called once at the beginning
draw() called at every 'frame'
http://gyazo.com/27d7717830a6fb80f910b4835aa781d7.png
Frame
60 images drawn on TV
24 images for movies
Each image called 'frame'
Getting mouse coordinates
Variables mouseX, mouseY represents current mouse position
http://gyazo.com/c58665ec399f87734b80f764407e6450.png
Mouse click events
mousePressed() called when mouse clicked
http://gyazo.com/a1845bc33d5483162db2b79b93efa36b.png
Functions/variables reference
http://gyazo.com/03e0b31830653be29ed0f628b7af6d9d.png
Publish on the Web
HTML files and applet generated
Can be copied to a Web server
http://pitecan.com/Puzzle/honeycomb/index.html http://gyazo.com/099c531208467217a89ec228856171a6.png
P5.js
https://p5js.org/ https://gyazo.com/42aa53c84d93659034f52370ca11e427
JavaScript version of Processing
Running P5.js
(will not be supported in the future)
Running on browsers
Recommended
References and tutorials
https://gyazo.com/c096a74372317bcfef987fb1a95e92a5
Tutorial and Examples
P5 resources
https://images-fe.ssl-images-amazon.com/images/I/51DCOj5HYVL._AC_US320_FMwebp_QL65_.jpg
https://images-na.ssl-images-amazon.com/images/I/61wLQ8X0G-L._SX379_BO1,204,203,200_.jpg
Running a P5.js program on Scrapbox
Write a code on Scrabox page
Use the "code notation"
code:test.js
alert('abc');
Create a link for running it
Built on FireBase
Literate Programming style!
We can write P5.js programs on Scrapbox
Example: drawing a normal distribution graph
https://gyazo.com/edbeca3c66ed7606e6fcc27dbf9b5bc8
code:normal.js
// Adding 10 random numbers and show the distribution
function setup(){
createCanvas(400,400)
histogram = []
for(i=0;i<100;i++) histogrami = 0 strokeWeight(0)
}
function draw(){
val = 0
for(i=0;i<10;i++) val += random(1/10)
fill('#ff0')
rect(0,0,400,400)
fill('blue')
for(i=0;i<100;i++)
rect(i*4,400-histogrami,4,histogrami) }
Example: Yuki-san
https://gyazo.com/86adfa800b4f9976fdfe65613c54593c
code:yuki.js
T=0
function setup(){
createCanvas(600,600)
noStroke()
}
function draw() {
fill('#000')
rect(0,0,600,600);
N=100
S=300
for (n=1; n<N; n++) {
r=n*2
fill('#fff')
R=(N-n)/10
t=T*n
ellipse(S+r*cos(t),S-r*sin(t),R,R)
T+=0.00001
console.log(T)
}
}
Yamabe's on P5
https://gyazo.com/0f86aad2c6be7650ad8a4ceea95b5d7f
code:rz.js
function setup(){
createCanvas(600,600);
background(128);
}
function draw(){
x = random(0,width);
y = random(0,height);
w = random(2,20);
noStroke();
if(x % 60 < 35)//xを60で割った余りが35未満だったら
fill(0,0,0);
else
fill(255,255,255);
ellipse(x, y, w, w);
}
Hello World
code:hello.js
alert('Hello, world!');
https://runp5.com/sfc-vis2019/12._Processing_and_P5.js/hello.js
Calculation
Calculating $ \sqrt{2}
code:sqrt.js
value = 100
for(;;){
alert(value)
value = (value + 2/value) / 2
}
Special functions in P5
setup()
Called once at startup
draw()
Repeatedly called while execution
Drawing a line
code:line.js
function setup(){
line(0,0,100,100);
}
Drawing a rectangle
code:rect.js
function setup(){
rect(10,10,80,80);
}
Drawing a rectangle
code:boldrect.js
function setup(){
stroke(255, 255, 0); // yellow
strokeWeight(10);
rect(10,10,80,80);
}
Drawing a rectangle
code:fillrect.js
function setup(){
fill('#00f'); // blue
rect(10,10,80,80);
}
Drawing a circle
code:circle.js
function setup(){
ellipse(50,50,30,30);
}
Using draw()
code:randrect.js
function setup(){
createCanvas(400, 400)
strokeWeight(0)
}
function draw(){ // called 30? times in a second
fill('blue')
posx = random(0,400)
posy = random(0,400)
rect(posx,posy,10,10)
}
Using draw()
code:randrect2.js
function setup(){
createCanvas(400, 400)
strokeWeight(0)
}
function draw(){
clear()
fill('blue')
posx = random(0,400)
posy = random(0,400)
rect(posx,posy,10,10)
}
Using mouse position
code:mouse.js
function setup(){
createCanvas(600, 600)
}
function draw(){
clear()
stroke('blue')
line(0,0,mouseX,mouseY) // predefined mouse coordinates
}
Getting mouse event
code:mouseevent.js
var value = 0;
function draw() {
fill(value);
rect(25, 25, 50, 50);
}
function mousePressed() {
if (value == 0) {
value = 255;
} else {
value = 0;
}
}
Drawing circles
https://gyazo.com/0ec9a6ad4dc1f39c260d34439bf827a8
code:drag.js
function setup() {
createCanvas(400,400);
fill(0);
}
function mouseDragged(){
ellipse(mouseX, mouseY, 20, 20);
}
Mouse move event
code:follow.js
function setup(){
createCanvas(400,400);
}
function draw(){
clear();
fill(0,0,255);
rect(mouseX,mouseY,40,40);
}
Drawing a fractal tree
code:tree.js
// The Nature of Code
// Daniel Shiffman
// Recursive Tree
// Renders a simple tree-like structure via recursion
// Branching angle calculated as a function of horizontal mouse position
var theta;
function setup() {
createCanvas(640, 360);
}
function draw() {
background(51);
// Let's pick an angle 0 to 90 degrees based on the mouse position
theta = map(mouseX,0,width,0,PI/2);
// Start the tree from the bottom of the screen
translate(width/2, height);
stroke(255);
//branch(120);
branch(mouseY); // Y座標で深さを変えるようにしてみた
}
function branch(len) {
// Each branch will be 2/3rds the size of the previous one
var sw = map(len,2,120,1,10);
strokeWeight(sw);
//strokeWeight(2);
line(0, 0, 0, -len);
// Move to the end of that line
translate(0, -len);
len *= 0.66;
// All recursive functions must have an exit condition!!!!
// Here, ours is when the length of the branch is 2 pixels or less
if (len > 2) {
push(); // Save the current state of transformation (i.e. where are we now)
rotate(theta); // Rotate by theta
branch(len); // Ok, now call myself to draw two new branches!!
pop(); // Whenever we get back here, we "pop" in order to restore the previous matrix state
// Repeat the same thing, only branch off to the "left" this time!
push();
rotate(-theta);
branch(len);
pop();
}
}
Escalator simulation
code:escalator.js
STRATEGY1 = 0; // left
STRATEGY2 = 1; // right
lspeedfactor = 1.0;
lgapfactor = 1.0;
rspeedfactor = 2.0;
rgapfactor = 3.0;
strategy = STRATEGY2;
var pair = location.search.substring(1).split('&');
for(var i=0; pairi; i++){ var kv = pairi.split('='); if(kv0 == 'ls') lspeedfactor = kv1; if(kv0 == 'lg') lgapfactor = kv1; if(kv0 == 'rs') rspeedfactor = kv1; if(kv0 == 'rg') rgapfactor = kv1; }
MOVING_LOWER = 0;
WAITING_LOWER = 1;
ASCENDING = 2;
UPPER = 3;
LEFT = 0;
RIGHT = 1;
llane = 220.0;
rlane = 250.0;
escheight = 460.0;
WINWIDTH = 500;
WINHEIGHT = 500;
NPERSONS = 50;
NSTAIRS = 15;
STAIRHEIGHT = 60;
STEPUNIT = 1;
steppos = 0;
waiting_l = 0;
waiting_r = 0;
done = false;
xspeed = 1.0;
persons = [];;
loops = 0;
var Person = function(){
this.x = 0.0;
this.y = 0.0;
this.status = MOVING_LOWER;
this.lr = LEFT;
};
function setup(){
createCanvas(WINWIDTH,WINHEIGHT);
frameRate(60);
for(var i=0;i<NPERSONS;i++){
}
}
function can_ascend_l(n){
var result = true;
for(var i=0;i<n;i++){
if(personsi.status == ASCENDING && personsi.y - personsn.y < STAIRHEIGHT * lgapfactor){ return false;
}
}
return true;
}
function can_ascend_r(n){
for(var i=0;i<n;i++){
if(personsi.status == ASCENDING && personsi.y - personsn.y < STAIRHEIGHT * rgapfactor){ return false;
}
}
return true;
}
function can_forward_lower(n){
for(var i=0;i<n;i++){
if(personsi.status == MOVING_LOWER && personsi.x - personsn.y < 30.0){ return false;
}
}
return true;
}
function can_forward_upper(n){
for(var i=0;i<NPERSONS;i++){
if(personsi.status == UPPER && personsi.x - personsn.x > 0.0 && personsi.x - personsn.x < 30.0){ return false;
}
}
return true;
}
function all_upper(){
for(var i=0;i<NPERSONS;i++){
if(personsi.status != UPPER) return false; }
return true;
}
function draw(){
if(done) return;
background(213,200,255);
for(var i=0;i<NSTAIRS;i++){
y = i * STAIRHEIGHT + steppos;
//line(llane-10+10,WINHEIGHT-y,rlane+10+20+10,WINHEIGHT-y);
fill(200,200,200);
strokeWeight(0);
rect(llane-10+10,WINHEIGHT-y,rlane-llane+40,STAIRHEIGHT/2);
}
steppos += STEPUNIT;
if(steppos >= STAIRHEIGHT){
steppos = 0;
}
for(var i=0;i<NPERSONS;i++){ // 駒をひとつずつ進める。
case MOVING_LOWER: // 下で移動中
if(personsi.x >= llane && // 左レーンまでたどりついたとき if(strategy == STRATEGY1){
if(waiting_l == 0 || waiting_l < waiting_r){
personsi.status = WAITING_LOWER; waiting_l++;
}
else {
personsi.lr = RIGHT; // 右で待つことにする }
}
else if(strategy == STRATEGY2){
if(waiting_l < waiting_r){
personsi.status = WAITING_LOWER; waiting_l++;
}
else {
personsi.lr = RIGHT; // 右で待つことにする }
}
}
else if(personsi.x >= rlane && // 右レーンまでたどりついたとき personsi.status = WAITING_LOWER; waiting_r++;
}
if(can_forward_lower(i)){ // 前に進める場合は一歩前に移動する
}
break;
case UPPER: // エスカレータからおりていて
if(can_forward_upper(i)){ // 前に進める場合は一歩前に移動する
}
break;
case WAITING_LOWER: // エスカレータ待ち状態で、
if(personsi.lr == LEFT && // 左で待っていて can_ascend_l(i) // 上に余地がある
){
personsi.status = ASCENDING; waiting_l--;
}
else if(personsi.lr == RIGHT && // 右で待っていて can_ascend_r(i) // 上に余地がある
){
personsi.status = ASCENDING; waiting_r--;
}
break;
case ASCENDING: //エスカレータに乗っていたら
if(personsi.y >= escheight){ // エスカレータで上まで到達していればおりる }
else {
personsi.y += STEPUNIT * lspeedfactor; // 1段上に移動する }
else {
personsi.y += STEPUNIT * rspeedfactor; // 1段上に移動する }
}
break;
}
}
strokeWeight(1);
for(var i=NPERSONS-1;i>=0;i--){
fill(255,255,0);
rect(personsi.x+10,WINHEIGHT-30-personsi.y,20,20); fill(0,0,0);
text(i+1,personsi.x+10+3,WINHEIGHT-30-personsi.y+14); }
if(! all_upper()){
loops++;
}
else {
done = true;
}
fill(0,0,0);
// text(millis(),20,20);
text(loops,20,20);
}
Playing Sound
code:sin.js
// canvas is not created if setup() is not defined
freq = $('<div>').text('440').appendTo($('body')) // div for freq
freqval = 440;
osc = new p5.TriOsc(); // set frequency and type
osc.amp(0.5);
osc.start();
$('<div>').appendTo($('body')).slider({ // jQuery UI slider
min: 50,
max: 1200,
value: 440,
slide: (event, ui) => {
freqval = ui.value
osc.freq(freqval)
freq.text(freqval)
osc.start()
}
});
Try your program on your Scrapbox project!
Summary
Try Processing and Canvas for visualization
Runs on standard browsers
Special IDE not required