diff --git a/1_pollution/0_basics/aqiget/aqiget.pde b/1_pollution/0_basics/aqiget/aqiget.pde new file mode 100644 index 0000000..c3cfc57 --- /dev/null +++ b/1_pollution/0_basics/aqiget/aqiget.pde @@ -0,0 +1,79 @@ +/* + Basic AQI JSON from waqi.info getting test based on jsonget example in http-requests library + https://github.com/acdean/HTTP-Requests-for-Processing + By: Mayank Joneja + Date: 02-01-2019 +*/ + +import http.requests.*; + +String AQI_TOKEN = "ENTER-TOKEN-HERE"; // Token generated from waqi.info +int POLLING_INTERVAL = 2; // Don't go faster than once per second preferably + +//String city = "delhi"; //city name or @station-id +String city = "@2556"; //R.K. Puram + +/* +To search for station-id, change the keyword field in: + https://api.waqi.info//search/?token=ENTER_TOKEN_HERE&keyword=rk puram + Take the "uid" parameter. +*/ + +public void setup() +{ + size(400,400); + smooth(); + println("Aqidata for " + city + " polled every " + POLLING_INTERVAL + " seconds:"); +} + +void draw() { + println("AQI value: " + getAqiVal(city)); + printParticleVals(city); + delay(POLLING_INTERVAL * 1000); // milliseconds +} + +JSONObject getAqiData(String city) { + String AQI_URL = "https://api.waqi.info/feed/" + city + "/?token=" + AQI_TOKEN; + GetRequest get = new GetRequest(AQI_URL); + get.send(); // program will wait untill the request is completed + + JSONObject response = parseJSONObject(get.getContent()); + + String status = response.getString("status"); + if(!status.equals("ok")) { + println("GET request to " + AQI_URL + " failed! Status: " + status); + println(response.getString("data")); + return null; + } + + //println("response: " + get.getContent()); + + // Parsing of response + JSONObject aqidata = response.getJSONObject("data"); + return aqidata; +} + +int getAqiVal(String city) { + JSONObject aqidata = getAqiData(city); + if(aqidata != null){ + return aqidata.getInt("aqi"); + } else { + return -1; + } +} + +void printParticleVals(String city) { + JSONObject aqidata = getAqiData(city); + if(aqidata != null){ + JSONObject iaqi = aqidata.getJSONObject("iaqi"); + + String particles[] = {"pm25", "pm10", "co", "o3"}; + + println("===========AQI Details========"); + for (String p : particles) { + float val = iaqi.getJSONObject(p).getFloat("v"); + println(p + " value: " + val); + } + println("=============================="); + } +} \ No newline at end of file diff --git a/1_pollution/0_basics/converge_2/converge_2.pde b/1_pollution/0_basics/converge_2/converge_2.pde index 7551fe1..a9360af 100644 --- a/1_pollution/0_basics/converge_2/converge_2.pde +++ b/1_pollution/0_basics/converge_2/converge_2.pde @@ -1,4 +1,24 @@ -private static boolean mode_kinect = true; +/* + Basic test for moving pollution particles based on processing's PVector tutorial: https://processing.org/tutorials/pvector/ + Date: 02-01-2020 + By: Mayank Joneja - botmayank@gmail.com +*/ + + +// Config +private static boolean mode_kinect = false; // true: Control with Kinect, false: Control with mouse + +// Random movement mode (only used when mode_kinect = false) +//0: No randomness, exactly follows mouse +//1: Follows mouse with some randomness +//2: Disregards mouse, totally random target positions + +static int random_mouse_mode = 2; + +// types of particles +int NO_2_5_PARTICLES = 40, NO_10_PARTICLES = 10; +Mover[] pm2_5_particles = new Mover[NO_2_5_PARTICLES]; +Mover[] pm10_particles = new Mover[NO_10_PARTICLES]; Mover[] movers = new Mover[20]; @@ -11,18 +31,49 @@ ArrayList bodies; void setup(){ size(1440, 800, P3D); background(0); - smooth(); + smooth(); + println("Running pollution particle test..."); + + float inertia, speed; + // Create new generic movers for(int i = 0; i < movers.length; i++){ - int gray = int(random(255)); - movers[i] = new Mover(); - //movers[i].col = color(gray, gray, gray); - //movers[i].orig_col = movers[i].col; + color col = color(random(50,255), random(10,90), 127); + float r = random(30.0, 90.0); + inertia = 15.0; + speed = 20.0; + movers[i] = new Mover(col, r, speed, inertia); + } + + // PM 2.5 particles + float r_2_5 = 25.0; + inertia = 10.0; // 10.0 makes particles overshoot target a lot + speed = 20.0; + for(int i = 0; i < pm2_5_particles.length; i++){ + color col = color(175, 71, 30); + pm2_5_particles[i] = new Mover(col, r_2_5, speed, inertia); + } + + // PM 10 particles + float r_10 = 100.0; + inertia = 60.0; + speed = 10.0; + for(int i = 0; i < pm10_particles.length; i++){ + color col = color(127, 173, 51); + pm10_particles[i] = new Mover(col, r_10, speed, inertia); + } + + // Other initializations + if(mode_kinect) { + kinect = new Kinect(this); + bodies = new ArrayList (); + println("======Kinect mode===="); + println("Move around in front of kinect to make particles follow!"); + println("====================="); + } else { + println("======Mouse mode===="); + println("Move around mouse to make particles follow!"); + println("====================="); } - kinect = new Kinect(this); - bodies = new ArrayList (); - - println("Converging PSEQ2"); - } void draw(){ @@ -30,47 +81,70 @@ void draw(){ fill(0,20); rect(0, 0, width, height); + //Kinect mode if(mode_kinect){ - //SkeletonData body; - //if body detected - if (bodies.size() != 0){ + //Body detected + if (bodies.size() != 0){ int bodyIndex = bodies.size() - 1; - //for(SkeletonData body : bodies){ SkeletonData body = bodies.get(bodyIndex); - //PVector body_pos = body.position; - //println("Body x, y:"); - //println(body.position.x); - //println(body.position.y); updatePositionKinect(body); - //} - } - else{ + } + // body not detected, buzz around + else{ int delta = 60; for(int i = 0; i < movers.length; i++){ - //movers[i].update(mouse_pos); movers[i].checkEdges(); movers[i].display(); movers[i].topspeed = 0.5; PVector goal = new PVector(random(movers[i].location.x-delta, movers[i].location.x+delta), random(movers[i].location.y-delta, movers[i].location.y+delta)); movers[i].update(goal); - } - //noStroke(); - //noFill(); - //background(0); - } - } - else{ // if mouse and not kinect - PVector mouse_pos = new PVector(mouseX,mouseY); - for(int i = 0; i < movers.length; i++){ - movers[i].update(mouse_pos); - movers[i].checkEdges(); - movers[i].display(); - } + } // for loop + } // else + } // mode_kinect + + // Mouse mode + else{ + int target_x = 0, target_y = 0; + if(random_mouse_mode == 0){ + // Follow mouse exactly + target_x = mouseX; + target_y = mouseY; + } else if(random_mouse_mode == 1) { + // Follow mouse with some randomness + target_x = mouseX + int(random(width/4)); + target_y = mouseY + int(random(height/4)); + } else { + // Totally random target position + target_x = int(random(width)); + target_y = int(random(height)); + } + + PVector mouse_pos = new PVector(target_x, target_y); + + // Normal Movers + //for(int i = 0; i < movers.length; i++){ + // movers[i].update(mouse_pos); + // movers[i].checkEdges(); + // movers[i].display(); + //} + + // PM 2.5 particles + for(int i = 0; i < pm2_5_particles.length; i++){ + pm2_5_particles[i].update(mouse_pos); + pm2_5_particles[i].checkEdges(); + pm2_5_particles[i].display(); + } + + // PM 10 particles + for(int i = 0; i < pm10_particles.length; i++){ + pm10_particles[i].update(mouse_pos); + pm10_particles[i].checkEdges(); + pm10_particles[i].display(); + } } } //Kinect events - void appearEvent(SkeletonData _s) { if (_s.trackingState == Kinect.NUI_SKELETON_NOT_TRACKED) @@ -119,8 +193,6 @@ void moveEvent(SkeletonData _b, SkeletonData _a) } void updatePositionKinect(SkeletonData body){ - //PVector body_pos = new PVector(body.position.x*width, body.position.y*height); - //PVector[] body_part_pos = body.skeletonPositions; for(int i = 0; i < movers.length; i++){ PVector pos = new PVector(body.skeletonPositions[i%body.skeletonPositions.length].x*width, body.skeletonPositions[i%body.skeletonPositions.length].y*height); fill(0,0,127); diff --git a/1_pollution/0_basics/converge_2/mover.pde b/1_pollution/0_basics/converge_2/mover.pde index a79a1aa..415d9c0 100644 --- a/1_pollution/0_basics/converge_2/mover.pde +++ b/1_pollution/0_basics/converge_2/mover.pde @@ -8,22 +8,21 @@ class Mover { float r; //Radius boolean move; int col_count = 1; + float overshoot_dist; //60.0 makes them stop too soon, 10.0 makes them overshoot - Mover(){ - //location = new PVector(width/2, height/2); + Mover(color c, float radius, float max_speed, float inertia){ location = new PVector(random(width), random(height)); - //velocity = new PVector(random(-2,2), random(-2,2)); - velocity = new PVector(0, 0); - topspeed = 10; - col = color(random(50,255), random(10,90), 0); - r = random(30.0, 90.0); - //acceleration = new PVector(-0.001,0.01); + velocity = new PVector(random(-2,2), random(-2,2)); + topspeed = max_speed; + col = c; + r = radius; + overshoot_dist = inertia; } void update(PVector destination){ //PVector mouse = new PVector(mouseX, mouseY); PVector dir = PVector.sub(destination, location); - if(dir.mag() < 60.0){ + if(dir.mag() < overshoot_dist){ move = false; } else{ @@ -66,14 +65,5 @@ class Mover { location.y = height; } - } - - void setRed(){ - if(col_count == 1){ - col = color(random(127, 255), 0, 0); - } - col_count++; -} - - -} \ No newline at end of file + } +} // class Mover \ No newline at end of file diff --git a/1_pollution/0_basics/shader_cloud/cloud1.png b/1_pollution/0_basics/shader_cloud/cloud1.png new file mode 100644 index 0000000..4ab2e0b Binary files /dev/null and b/1_pollution/0_basics/shader_cloud/cloud1.png differ diff --git a/1_pollution/0_basics/shader_cloud/cloud2.png b/1_pollution/0_basics/shader_cloud/cloud2.png new file mode 100644 index 0000000..644d8fd Binary files /dev/null and b/1_pollution/0_basics/shader_cloud/cloud2.png differ diff --git a/1_pollution/0_basics/shader_cloud/cloud3.png b/1_pollution/0_basics/shader_cloud/cloud3.png new file mode 100644 index 0000000..644d8fd Binary files /dev/null and b/1_pollution/0_basics/shader_cloud/cloud3.png differ diff --git a/1_pollution/0_basics/shader_cloud/shader_cloud.pde b/1_pollution/0_basics/shader_cloud/shader_cloud.pde new file mode 100644 index 0000000..0d53dae --- /dev/null +++ b/1_pollution/0_basics/shader_cloud/shader_cloud.pde @@ -0,0 +1,54 @@ +/* + Random clouds filling up screen like fog based on Shaders Tutorial 10.2 + https://processing.org/tutorials/pshader/ + By: Mayank Joneja + Date: 03-01-2020 +*/ + +PShader pointShader; +PImage cloud1; +PImage cloud2; +PImage cloud3; + +float weight = 100; +int target_x = 0, target_y = 0; +int y_margin = 50; +int frame_counter = 0; + +void setup() { + size(1440, 960, P3D); + + pointShader = loadShader("spritefrag.glsl", "spritevert.glsl"); + pointShader.set("weight", weight); + cloud1 = loadImage("cloud1.png"); + cloud2 = loadImage("cloud2.png"); + cloud3 = loadImage("cloud3.png"); + pointShader.set("sprite", cloud2); + + strokeWeight(weight); + strokeCap(SQUARE); + stroke(255, 70); + + background(0); +} + +void draw() { + + shader(pointShader, POINTS); + if(frame_counter <= 300) { + target_y = int(random(2 * height/3 + 100, height)); + } else { + target_y = int(random(2 * height/3, height)); + } + + //target_x = int(random(width)); + + target_y = int(random(target_y - y_margin, target_y + y_margin)); + + target_x += 3; + if (target_x >= width) target_x = 0; + if(!mousePressed) + point(target_x, target_y); + + frame_counter++; +} \ No newline at end of file diff --git a/1_pollution/0_basics/shader_cloud/spritefrag.glsl b/1_pollution/0_basics/shader_cloud/spritefrag.glsl new file mode 100644 index 0000000..c9e35f2 --- /dev/null +++ b/1_pollution/0_basics/shader_cloud/spritefrag.glsl @@ -0,0 +1,14 @@ + +#ifdef GL_ES +precision mediump float; +precision mediump int; +#endif + +uniform sampler2D sprite; + +varying vec4 vertColor; +varying vec2 texCoord; + +void main() { + gl_FragColor = texture2D(sprite, texCoord) * vertColor; +} \ No newline at end of file diff --git a/1_pollution/0_basics/shader_cloud/spritevert.glsl b/1_pollution/0_basics/shader_cloud/spritevert.glsl new file mode 100644 index 0000000..3b74d46 --- /dev/null +++ b/1_pollution/0_basics/shader_cloud/spritevert.glsl @@ -0,0 +1,22 @@ +uniform mat4 projection; +uniform mat4 modelview; + +uniform float weight; + +attribute vec4 position; +attribute vec4 color; +attribute vec2 offset; + +varying vec4 vertColor; +varying vec2 texCoord; + +void main() { + vec4 pos = modelview * position; + vec4 clip = projection * pos; + + gl_Position = clip + projection * vec4(offset, 0, 0); + + texCoord = (vec2(0.5) + offset / weight); + + vertColor = color; +} \ No newline at end of file diff --git a/1_pollution/1_final/pollution_earthy/mover.pde b/1_pollution/1_final/pollution_earthy/mover.pde deleted file mode 100644 index 07d479a..0000000 --- a/1_pollution/1_final/pollution_earthy/mover.pde +++ /dev/null @@ -1,68 +0,0 @@ -class Mover { - PVector location; - PVector velocity; - PVector acceleration; - float topspeed; - color col; - float r; //Radius - boolean move; - - Mover(){ - //location = new PVector(width/2, height/2); - location = new PVector(random(width), random(height)); - //velocity = new PVector(random(-2,2), random(-2,2)); - velocity = new PVector(0, 0); - topspeed = 2; - col = color(random(50,255),random(10, 90), 0); - r = random(30.0, 130.0); - //acceleration = new PVector(-0.001,0.01); -} - - void update(PVector destination){ - //PVector mouse = new PVector(mouseX, mouseY); - PVector dir = PVector.sub(destination, location); - if(dir.mag() < 10.0){ - move = false; - } - else{ - move = true; - } - - dir.normalize(); - dir.mult(0.5); - acceleration = dir; - - if(move){ - velocity.add(acceleration); - } - else{ - velocity.set(0.0,0.0); - } - - //velocity.add(acceleration); - velocity.limit(topspeed); - location.add(velocity); - - } - - void display(){ - noStroke(); - fill(col); - ellipse(location.x, location.y, r, r); - } - - void checkEdges(){ - if (location.x > width){ - location.x = 0; - } else if(location.x < 0) { - location.x = width; - } - - if(location.y > height){ - location.y = 0; - } else if (location.y < 0) { - location.y = height; - } - - } -} \ No newline at end of file diff --git a/1_pollution/1_final/pollution_earthy/pollution_earthy.pde b/1_pollution/1_final/pollution_earthy/pollution_earthy.pde deleted file mode 100644 index d0b208d..0000000 --- a/1_pollution/1_final/pollution_earthy/pollution_earthy.pde +++ /dev/null @@ -1,149 +0,0 @@ -/* - Pollution Sequence - Brief: Pollution is depicted through random circular particles which stick to the human skeleton detected by kinect - Date: 23-10-2017 - By: Mayank Joneja - botmayank@gmail.com - Ameet Singh - wayward72@gmail.com - - Note: Install the TTF font in the data folder for the Subway Ticker font from http://www.1001fonts.com/subway-ticker-font.html - before running the sketch -*/ - -Mover[] movers = new Mover[40]; - -//Kinect imports -import kinect4WinSDK.Kinect; -import kinect4WinSDK.SkeletonData; -Kinect kinect; -ArrayList bodies; - -//Text init -String[] headlines = { - "DANCE TO THE POLLUTION", - "new study shows that pollution is quite democratic.", - }; - -PFont f; // Global font variable -float x; // horizontal location of headline -int index = 0; -int text_speed = 2; - -volatile boolean header = true; - -void setup(){ - size(1920, 1080, P3D); - background(0); - smooth(); - for(int i = 0; i < movers.length; i++){ - movers[i] = new Mover(); - } - kinect = new Kinect(this); - bodies = new ArrayList (); - - println("Earthy Colors Pollution sequence by Mayank Joneja, Ameet Singh"); - f = createFont("Subway Ticker",30,true); - // Initialize headline offscreen to the right - x = width; -} - -void draw(){ - //If no bodies, show Header - if(header == true){ - background(0); - fill(#ff0000); - displayHeader(); - } - else{ - noStroke(); - fill(0, 20); - rect(0, 0, width, height); - SkeletonData body; - //if body detected - if (bodies.size() != 0){ - int bodyIndex = bodies.size() - 1; - body = bodies.get(bodyIndex); - updatePositionKinect(body); - } - } -} - -//Kinect events - -void appearEvent(SkeletonData _s) -{ - if (_s.trackingState == Kinect.NUI_SKELETON_NOT_TRACKED) - { - return; - } - println("Body appeared!"); - header = false; - synchronized(bodies) { - bodies.add(_s); - } -} - -void disappearEvent(SkeletonData _s) -{ - println("Body gone!"); - header = true; - synchronized(bodies) { - for (int i=bodies.size ()-1; i>=0; i--) - { - if (_s.dwTrackingID == bodies.get(i).dwTrackingID) - { - bodies.remove(i); - } - } - } -} - -void moveEvent(SkeletonData _b, SkeletonData _a) -{ - if (_a.trackingState == Kinect.NUI_SKELETON_NOT_TRACKED) - { - return; - } - //println("Body moving!"); - synchronized(bodies) { - for (int i=bodies.size ()-1; i>=0; i--) - { - if (_b.dwTrackingID == bodies.get(i).dwTrackingID) - { - bodies.get(i).copy(_a); - break; - } - } - } -} - -void updatePositionKinect(SkeletonData body){ - //PVector body_pos = new PVector(body.position.x*width, body.position.y*height); - //PVector[] body_part_pos = body.skeletonPositions; - for(int i = 0; i < movers.length; i++){ - //PVector pos = new PVector(body_part_pos[i%movers.length].x*width, body_part_pos[i%movers.length].x*height); - PVector pos = new PVector(body.skeletonPositions[i%body.skeletonPositions.length].x*width, body.skeletonPositions[i%body.skeletonPositions.length].y*height); - fill(0,0,127); - ellipse(pos.x, pos.y, 16, 20); - movers[i].update(pos); - movers[i].checkEdges(); - movers[i].display(); - } -} - -void displayHeader(){ - // Display headline at x location - textFont(f, 64); - textAlign(LEFT); - text(headlines[index],x,height/2); - - // Decrement x - x = x - text_speed; - - // If x is less than the negative width, - // then it is off the screen - float w = textWidth(headlines[index]); - if (x < -w) { - x = width; - index = (index + 1) % headlines.length; - } -} \ No newline at end of file diff --git a/1_pollution/1_final_sequences/dance_pollution_aqi/dance_pollution_aqi/dance_pollution_aqi.pde b/1_pollution/1_final_sequences/dance_pollution_aqi/dance_pollution_aqi/dance_pollution_aqi.pde new file mode 100644 index 0000000..266f7e1 --- /dev/null +++ b/1_pollution/1_final_sequences/dance_pollution_aqi/dance_pollution_aqi/dance_pollution_aqi.pde @@ -0,0 +1,494 @@ +/* + Pollution Sequence + Brief: Pollution is depicted through random circular particles which stick to the human skeleton detected by kinect + AQI data is pulled from https://waqi.info + Date: 04-01-2020 + By: Mayank Joneja - botmayank@gmail.com + Ameet Singh - wayward72@gmail.com +*/ + +import kinect4WinSDK.Kinect; +import kinect4WinSDK.SkeletonData; +import http.requests.*; + +// Config +private static boolean mode_kinect = true; // true: Control with Kinect, false: Control with mouse + +//Kinect globals +Kinect kinect; +ArrayList bodies; + +//Text globals +String[] headlines = { + "DANCE TO THE POLLUTION", + "A new study shows that pollution is quite democratic.", + }; + +PFont text_f; // Global font variable +float text_x; // horizontal location of headline +int text_speed = 2; +volatile boolean header = true; +int headline_index = 0; + +//AQI globals +String AQI_TOKEN = "ENTER-TOKEN-HERE"; // Token generated from waqi.info + + +/* +@2556 : R.K Puram, Delhi, India +@1929 : Aichi, Japan +@5724 : London, UK +@10707: Sri Aurobindo Marg, New Delhi, India +@11278: Knowledge Park - III, Greater Noida, India +@10113: ITI Jahangirpuri, Delhi, Delhi, India +@10119: National Institute of Malaria Research, Dwarka, Delhi, India +*/ + +StringDict city_list; + +//String city = "@2556"; //R.K. Puram +//String city = "@11278"; //Greater Noida +String city = "@1929"; + +//Particle globals +ArrayList movers, pm25_particles, pm10_particles; //movers are all other gases +int MIN_PARTICLES_25 = 3; +int MIN_PARTICLES_10 = 3; +int MAX_MOVERS = 150; +int MAX_PM_25 = 100; +int MAX_PM_10 = 100; +int AQI_MAX = 600; + +// common speeds and inertias for particles based on AQI +float[] aqi_speeds = {5.0, 8.0, 10.0, 12.0, 15.0, 20.0}; +float[] aqi_inertias = {2.0, 5.0, 10.0, 15.0, 20.0, 25.0}; + +void setup(){ + println("AQI and pollutant data sequence by Mayank Joneja, Ameet Singh"); + + fullScreen(); + background(0); + smooth(); + + /* City list for text */ + city_list = new StringDict(); + city_list.set("@2556", "R.K Puram, Delhi, India"); + city_list.set("@1929", "Aichi, Japan"); + city_list.set("@5724", "London, UK"); + city_list.set("@10707", "Sri Aurobindo Marg, New Delhi, India"); + city_list.set("@11278", "Knowledge Park - III, Greater Noida, India"); + city_list.set("@10113", "ITI Jahangirpuri, Delhi, Delhi, India"); + city_list.set("@10119", "National Institute of Malaria Research, Dwarka, Delhi, India"); + + /* Find out AQI for PM2.5 and PM10 */ + println("Getting AQI Data for station-id: " + city); + int aqi_num = getAqiVal(city); + println("AQI single value: " + aqi_num); + + printParticleVals(city); + FloatList aqivals = getParticleVals(city); + float aqi_num_25 = aqivals.get(0); // pm 2.5 + float aqi_num_10 = aqivals.get(1); // pm 10 + println("No. of PM2.5 particles: " + aqi_num_25 + " pm10 particles: " + aqi_num_10 ); + + /* Initialize particles for PM10 and PM2.5 */ + int num_25 = int(map(aqi_num_25, 0, AQI_MAX, MIN_PARTICLES_25, MAX_PM_25)); + int num_10 = int(map(aqi_num_10, 0, AQI_MAX, MIN_PARTICLES_10, MAX_PM_10)); + + int num_gases = MAX_MOVERS - (num_25 + num_10); + float num_aqi_gases = aqivals.get(2) + aqivals.get(3); + num_gases = int(map(num_aqi_gases, 0, 100, 0, num_gases)); + + println("Initializing particles with: "); + println("#gases = " + num_gases); + println("#PM2.5 particles = " + num_25); + println("#PM10 particles = " + num_10); + println("Assuming MAX_AQI = " + AQI_MAX); + + movers = new ArrayList(); + pm25_particles = new ArrayList(); + pm10_particles = new ArrayList(); + + // Initialize particles based on AQI + init_gases(num_gases); + init_pm10(num_10, int(aqi_num_10)); + init_pm25(num_25, int(aqi_num_25)); + + // Kinect init + kinect = new Kinect(this); + bodies = new ArrayList (); + + // Ticker text init + text_f = createFont("Subway Ticker",30,true); + // Initialize headline offscreen to the right + text_x = width; +} + +void init_pm25 (int num_25, int aqi) { + int aqi_cat = getAqiCategory(aqi); //0-5 + //PM2.5 + float[] pm25_radii = {15.0, 20.0, 25.0, 30.0, 40.0, 60.0, 80.0}; + + color col = getAqiCategoryColor(aqi); + float r = pm25_radii[aqi_cat]; + float speed = aqi_speeds[aqi_cat]; + float inertia = aqi_inertias[aqi_cat]; + + for(int i = 0; i < num_25; i++){ + pm25_particles.add(new Mover(col, r, speed, inertia)); + } +} + +void init_pm10 (int num_10, int aqi) { + int aqi_cat = getAqiCategory(aqi); //0-5 + //PM10 + float[] pm10_radii = {30.0, 40.0, 50.0, 60.0, 80.0, 120.0, 160.0}; + + color col = getAqiCategoryColorDark(aqi); + float r = pm10_radii[aqi_cat]; + float speed = aqi_speeds[aqi_cat]; + float inertia = aqi_inertias[aqi_cat]; + + for(int i = 0; i < num_10; i++){ + pm10_particles.add(new Mover(col, r, speed, inertia)); + } +} + +void init_gases(int num_gases) { + float inertia, speed; + for(int i = 0; i < num_gases; i++){ + color col = color(random(50,255), random(10,90), 0); + float r = random(2.0, 4.0); + inertia = 15.0; + speed = 20.0; + movers.add(new Mover(col, r, speed, inertia)); + } +} + +void draw(){ + if(mode_kinect){ + //If no bodies, show Header + if(header == true){ + displayHeader(); + } else { + showBody(); + } + } else { //mouse mode + followMouse(1); + } + displayCity(); +} + +//Mouse mode +void followMouse(int random_mouse_mode) { + // Random movement mode (only used when mode_kinect = false) + //0: No randomness, exactly follows mouse + //1: Follows mouse with some randomness + //2: Disregards mouse, totally random target positions + + int target_x = 0, target_y = 0; + // Clear screen and do alpha blending + noStroke(); + fill(0,20); + rect(0, 0, width, height); + + if(random_mouse_mode == 0){ + // Follow mouse exactly + target_x = mouseX; + target_y = mouseY; + } else if(random_mouse_mode == 1) { + // Follow mouse with some randomness + target_x = mouseX + int(random(width/4)); + target_y = mouseY + int(random(height/4)); + } else { + // Totally random target position + target_x = int(random(width)); + target_y = int(random(height)); + } + + PVector mouse_pos = new PVector(target_x, target_y); + // Normal Movers + for(int i = 0; i < movers.size(); i++){ + movers.get(i).update(mouse_pos); + } + + //PM2.5 + for(int i = 0; i < pm25_particles.size(); i++){ + pm25_particles.get(i).update(mouse_pos); + } + + //PM10 + for(int i = 0; i < pm10_particles.size(); i++){ + pm10_particles.get(i).update(mouse_pos); + } +} + +/*******************Kinect Methods*******************/ +void showBody() { + noStroke(); + fill(0, 20); //black, alpha + rect(0, 0, width, height); + SkeletonData body; + //if body detected + if (bodies.size() != 0){ + int bodyIndex = bodies.size() - 1; + body = bodies.get(bodyIndex); + updatePositionKinect(body); + } +} + +void appearEvent(SkeletonData _s) +{ + if (_s.trackingState == Kinect.NUI_SKELETON_NOT_TRACKED) + { + return; + } + println("Body appeared!"); + header = false; + synchronized(bodies) { + bodies.add(_s); + } +} + +void disappearEvent(SkeletonData _s) +{ + println("Body gone!"); + //header = false; + synchronized(bodies) { + for (int i=bodies.size ()-1; i>=0; i--) + { + if (_s.dwTrackingID == bodies.get(i).dwTrackingID) + { + bodies.remove(i); + } + } + } + randomizeMovers(); +} + +void moveEvent(SkeletonData _b, SkeletonData _a) +{ + if (_a.trackingState == Kinect.NUI_SKELETON_NOT_TRACKED) + { + return; + } + //println("Body moving!"); + synchronized(bodies) { + for (int i=bodies.size ()-1; i>=0; i--) + { + if (_b.dwTrackingID == bodies.get(i).dwTrackingID) + { + bodies.get(i).copy(_a); + break; + } + } + } +} + +void updatePositionKinect(SkeletonData body){ + PVector body_pos = new PVector(body.position.x*width, body.position.y*height); + int target_x = 0, target_y = 0; + float body_x = 0, body_y = 0; + if(body_pos.mag() > 10){ // not at the edge of the screen/partially out + // Draw body ellipses + for (int i = 0; i < body.skeletonPositions.length; i++) { + // update body ellipse + colorMode(RGB, 255); + body_x = body.skeletonPositions[i].x*width; + body_y = body.skeletonPositions[i].y*height; + + PVector body_part_pos = new PVector(body_x, body_y); + fill(0,0,127); //blue ellipse for skeleton body + ellipse(body_part_pos.x, body_part_pos.y, 16, 20); + } + //PM2.5 stick to human + small amount of randomness + for(int i = 0; i < pm25_particles.size(); i++){ + body_x = body.skeletonPositions[i%body.skeletonPositions.length].x*width; + body_y = body.skeletonPositions[i%body.skeletonPositions.length].y*height; + target_x = int(body_x + random(-width/10, width/10)); + target_y = int(body_y + random(-height/10, height/10)); + PVector pos = new PVector(target_x, target_y); + pm25_particles.get(i).update(pos); + } + //PM 10 stick to human + some more randomness + for(int i = 0; i < pm10_particles.size(); i++){ + target_x = int(body.skeletonPositions[i%body.skeletonPositions.length].x*width + random(-width/4, width/4)); + target_y = int(body.skeletonPositions[i%body.skeletonPositions.length].y*height + random(-height/4, height/4)); + PVector pos = new PVector(target_x, target_y); + pm10_particles.get(i).update(pos); + } + // Gases random + for(int i = 0; i < movers.size(); i++){ + PVector pos = new PVector(random(width), random(height)); + movers.get(i).update(pos); + } + } //if + else{ + randomizeMovers(); + } +} + +void randomizeMovers(){ + for(int i = 0; i< movers.size(); i++){ + PVector pos = new PVector(random(width), random(height)); + movers.get(i).update(pos); + } + + //PM2.5 + for(int i = 0; i < pm25_particles.size(); i++){ + PVector pos = new PVector(random(width), random(height)); + pm25_particles.get(i).update(pos); + } + + //PM10 + for(int i = 0; i < pm10_particles.size(); i++){ + PVector pos = new PVector(random(width), random(height)); + pm10_particles.get(i).update(pos); + } +} + +/*******************Ticker Header Methods*******************/ +void displayHeader(){ + background(0); + fill(#ff0000); + + // Display headline at text_x location + textFont(text_f, 64); + textAlign(LEFT); + text(headlines[headline_index], text_x,height/2); + + // Decrement x + text_x = text_x - text_speed; + + // If x is less than the negative width, + // then it is off the screen + float w = textWidth(headlines[headline_index]); + if (text_x < -w) { + text_x = width; + headline_index = (headline_index + 1) % headlines.length; + } +} + +void displayCity() { + int padding = 20; + textFont(text_f, 48); + textAlign(RIGHT); + text(city_list.get(city), width - padding, height - padding); // bottom right corner +} + +/************************AQI Methods*************************/ + +JSONObject getAqiData(String city) { + String AQI_URL = "https://api.waqi.info/feed/" + city + "/?token=" + AQI_TOKEN; + GetRequest get = new GetRequest(AQI_URL); + get.send(); // program will wait untill the request is completed + + JSONObject response = parseJSONObject(get.getContent()); + + String status = response.getString("status"); + if(!status.equals("ok")) { + println("GET request to " + AQI_URL + " failed! Status: " + status); + println(response.getString("data")); + return null; + } + + //println("response: " + get.getContent()); + + // Parsing of response + JSONObject aqidata = response.getJSONObject("data"); + return aqidata; +} + +int getAqiVal(String city) { + JSONObject aqidata = getAqiData(city); + if(aqidata != null){ + return aqidata.getInt("aqi"); + } else { + return -1; + } +} + +FloatList getParticleVals(String city) { + // Returns a float list of particle vals: "pm25", "pm10", "co", "o3" + + FloatList vals = new FloatList(); + JSONObject aqidata = getAqiData(city); + + if(aqidata != null){ + JSONObject iaqi = aqidata.getJSONObject("iaqi"); + String particles[] = {"pm25", "pm10", "co", "o3"}; + + for (String p : particles) { + float val = iaqi.getJSONObject(p).getFloat("v"); + vals.append(val); + } + } + return vals; +} + +void printParticleVals(String city) { + JSONObject aqidata = getAqiData(city); + if(aqidata != null){ + JSONObject iaqi = aqidata.getJSONObject("iaqi"); + + String particles[] = {"pm25", "pm10", "co", "o3"}; + + println("===========AQI Details========"); + for (String p : particles) { + float val = iaqi.getJSONObject(p).getFloat("v"); + println(p + " value: " + val); + } + println("=============================="); + } +} + +color getAqiCategoryColor(int aqi_num) { + int aqi_cat = getAqiCategory(aqi_num); + + int[] aqi_hues = {121, 59, 24, 357, 333, 331, 0}; // HSV Hue values in 360 deg + int[] aqi_saturations = {77, 71, 83, 92, 90, 95, 0}; // HSV Sat values in 0-100 + int[] aqi_brightnesses = {88, 100, 99, 99, 59, 29, 50}; // HSV Brightnes values in 0-100 + + int aqi_hue = int(map(aqi_hues[aqi_cat], 0, 360, 0, 100)); + colorMode(HSB, 100); + color aqi_color = color(aqi_hue, aqi_saturations[aqi_cat], aqi_brightnesses[aqi_cat]); + + return aqi_color; +} + +color getAqiCategoryColorDark(int aqi_num) { + int aqi_cat = getAqiCategory(aqi_num); + + int[] aqi_hues = {121, 59, 24, 357, 333, 331, 0}; // HSV Hue values in 360 deg + int[] aqi_saturations = {77, 71, 83, 92, 90, 95, 0}; // HSV Sat values in 0-100 + int[] aqi_brightnesses = {88, 100, 99, 99, 59, 29, 50}; // HSV Brightnes values in 0-100 + + int aqi_hue = int(map(aqi_hues[aqi_cat], 0, 360, 0, 100)); + colorMode(HSB, 100); + color aqi_color = color(aqi_hue, aqi_saturations[aqi_cat], aqi_brightnesses[aqi_cat] - 25); + + return aqi_color; +} + +int getAqiCategory(int aqi_num) { + int aqi_cat = 0; + int[] aqi_level = {0, 51, 101, 151, 201, 301}; + + if(aqi_num > aqi_level[0] && aqi_num < aqi_level[1]) { + aqi_cat = 0; // Good - Green + } else if(aqi_num > aqi_level[1] && aqi_num < aqi_level[2]) { + aqi_cat = 1; // Moderate - Yellow + } else if(aqi_num > aqi_level[2] && aqi_num < aqi_level[3]) { + aqi_cat = 2; // Unhealthy for sensitive groups - Orange + } else if(aqi_num > aqi_level[3] && aqi_num < aqi_level[4]) { + aqi_cat = 3; // Unhealthy - Red + } else if(aqi_num > aqi_level[4] && aqi_num < aqi_level[5]) { + aqi_cat = 4; // Very Unhealthy - Purple + } else if(aqi_num > aqi_level[5]) { + aqi_cat = 5; // Hazardous - Maroon + } else { + println("Unexpected aqi_num: " + aqi_num); + aqi_cat = 5; + } + return aqi_cat; +} \ No newline at end of file diff --git a/1_pollution/1_final/pollution_earthy/data/SUBWT___.ttf b/1_pollution/1_final_sequences/dance_pollution_aqi/dance_pollution_aqi/data/SUBWT___.ttf similarity index 100% rename from 1_pollution/1_final/pollution_earthy/data/SUBWT___.ttf rename to 1_pollution/1_final_sequences/dance_pollution_aqi/dance_pollution_aqi/data/SUBWT___.ttf diff --git a/1_pollution/PSEQ1/slow_earthy/mover.pde b/1_pollution/1_final_sequences/dance_pollution_aqi/dance_pollution_aqi/mover.pde similarity index 56% rename from 1_pollution/PSEQ1/slow_earthy/mover.pde rename to 1_pollution/1_final_sequences/dance_pollution_aqi/dance_pollution_aqi/mover.pde index 50aa54e..3d98fef 100644 --- a/1_pollution/PSEQ1/slow_earthy/mover.pde +++ b/1_pollution/1_final_sequences/dance_pollution_aqi/dance_pollution_aqi/mover.pde @@ -8,22 +8,21 @@ class Mover { float r; //Radius boolean move; int col_count = 1; + float overshoot_dist; //60.0 makes them stop too soon, 10.0 makes them overshoot - Mover(){ - //location = new PVector(width/2, height/2); + Mover(color c, float radius, float max_speed, float inertia){ location = new PVector(random(width), random(height)); - //velocity = new PVector(random(-2,2), random(-2,2)); - velocity = new PVector(0, 0); - topspeed = 5; - col = color(random(50,255), random(10,90), 0); - r = random(30.0, 90.0); - //acceleration = new PVector(-0.001,0.01); + velocity = new PVector(random(-2,2), random(-2,2)); + topspeed = max_speed; + col = c; + r = radius; + overshoot_dist = inertia; } void update(PVector destination){ //PVector mouse = new PVector(mouseX, mouseY); PVector dir = PVector.sub(destination, location); - if(dir.mag() < 10.0){ + if(dir.mag() < overshoot_dist){ move = false; } else{ @@ -44,7 +43,8 @@ class Mover { //velocity.add(acceleration); velocity.limit(topspeed); location.add(velocity); - + checkEdges(); + display(); } void display(){ @@ -54,26 +54,16 @@ class Mover { } void checkEdges(){ - if (location.x > width){ - location.x = 0; - } else if(location.x < 0) { - location.x = width; - } + if (location.x > width){ + location.x = 0; + } else if(location.x < 0) { + location.x = width; + } - if(location.y > height){ - location.y = 0; - } else if (location.y < 0) { - location.y = height; + if(location.y > height){ + location.y = 0; + } else if (location.y < 0) { + location.y = height; + } } - - } - - void setRed(){ - if(col_count == 1){ - col = color(random(127, 255), 0, 0); - } - col_count++; -} - - -} \ No newline at end of file +} // class Mover \ No newline at end of file diff --git a/1_pollution/PSEQ1/text_earthy/text_earthy/data/SUBWT___.ttf b/1_pollution/1_final_sequences/dance_pollution_orig/text_earthy/data/SUBWT___.ttf similarity index 100% rename from 1_pollution/PSEQ1/text_earthy/text_earthy/data/SUBWT___.ttf rename to 1_pollution/1_final_sequences/dance_pollution_orig/text_earthy/data/SUBWT___.ttf diff --git a/1_pollution/PSEQ1/text_earthy/text_earthy/mover.pde b/1_pollution/1_final_sequences/dance_pollution_orig/text_earthy/mover.pde similarity index 100% rename from 1_pollution/PSEQ1/text_earthy/text_earthy/mover.pde rename to 1_pollution/1_final_sequences/dance_pollution_orig/text_earthy/mover.pde diff --git a/1_pollution/PSEQ1/text_earthy/text_earthy/text_earthy.pde b/1_pollution/1_final_sequences/dance_pollution_orig/text_earthy/text_earthy.pde similarity index 100% rename from 1_pollution/PSEQ1/text_earthy/text_earthy/text_earthy.pde rename to 1_pollution/1_final_sequences/dance_pollution_orig/text_earthy/text_earthy.pde diff --git a/1_pollution/PSEQ1/fast_red/fast_red.pde b/1_pollution/PSEQ1/fast_red/fast_red.pde deleted file mode 100644 index e8f2919..0000000 --- a/1_pollution/PSEQ1/fast_red/fast_red.pde +++ /dev/null @@ -1,119 +0,0 @@ -private static boolean mode_kinect = true; - -Mover[] movers = new Mover[30]; - -//Kinect imports -import kinect4WinSDK.Kinect; -import kinect4WinSDK.SkeletonData; -Kinect kinect; -ArrayList bodies; - -void setup(){ - size(1920, 1080, P3D); - background(0); - smooth(); - for(int i = 0; i < movers.length; i++){ - movers[i] = new Mover(); - } - kinect = new Kinect(this); - bodies = new ArrayList (); - - println("Converging PSEQ2"); - -} - -void draw(){ - noStroke(); - fill(0, 10); - rect(0, 0, width, height); - - if(mode_kinect){ - SkeletonData body; - //if body detected - if (bodies.size() != 0){ - int bodyIndex = bodies.size() - 1; - body = bodies.get(bodyIndex); - //PVector body_pos = body.position; - //println("Body x, y:"); - //println(body.position.x); - //println(body.position.y); - updatePositionKinect(body); - } - else{ - noStroke(); - noFill(); - background(0); - } - } - else{ // if mouse and not kinect - PVector mouse_pos = new PVector(mouseX,mouseY); - for(int i = 0; i < movers.length; i++){ - movers[i].update(mouse_pos); - movers[i].checkEdges(); - movers[i].display(); - } - } -} - -//Kinect events - -void appearEvent(SkeletonData _s) -{ - if (_s.trackingState == Kinect.NUI_SKELETON_NOT_TRACKED) - { - return; - } - println("Body appeared!"); - synchronized(bodies) { - bodies.add(_s); - } -} - - -void disappearEvent(SkeletonData _s) -{ - println("Body gone!"); - synchronized(bodies) { - for (int i=bodies.size ()-1; i>=0; i--) - { - if (_s.dwTrackingID == bodies.get(i).dwTrackingID) - { - bodies.remove(i); - } - } - } -} - - -void moveEvent(SkeletonData _b, SkeletonData _a) -{ - if (_a.trackingState == Kinect.NUI_SKELETON_NOT_TRACKED) - { - return; - } - //println("Body moving!"); - synchronized(bodies) { - for (int i=bodies.size ()-1; i>=0; i--) - { - if (_b.dwTrackingID == bodies.get(i).dwTrackingID) - { - bodies.get(i).copy(_a); - break; - } - } - } -} - -void updatePositionKinect(SkeletonData body){ - //PVector body_pos = new PVector(body.position.x*width, body.position.y*height); - //PVector[] body_part_pos = body.skeletonPositions; - for(int i = 0; i < movers.length; i++){ - //PVector pos = new PVector(body_part_pos[i%movers.length].x*width, body_part_pos[i%movers.length].x*height); - PVector pos = new PVector(body.skeletonPositions[i%body.skeletonPositions.length].x*width, body.skeletonPositions[i%body.skeletonPositions.length].y*height); - fill(0,0,127); - ellipse(pos.x, pos.y, 16, 20); - movers[i].update(pos); - movers[i].checkEdges(); - movers[i].display(); - } -} \ No newline at end of file diff --git a/1_pollution/PSEQ1/fast_red/mover.pde b/1_pollution/PSEQ1/fast_red/mover.pde deleted file mode 100644 index 122b4c0..0000000 --- a/1_pollution/PSEQ1/fast_red/mover.pde +++ /dev/null @@ -1,68 +0,0 @@ -class Mover { - PVector location; - PVector velocity; - PVector acceleration; - float topspeed; - color col; - float r; //Radius - boolean move; - - Mover(){ - //location = new PVector(width/2, height/2); - location = new PVector(random(width), random(height)); - //velocity = new PVector(random(-2,2), random(-2,2)); - velocity = new PVector(0, 0); - topspeed = 5; - col = color(random(50,255), 0, 0); - r = random(30.0, 90.0); - //acceleration = new PVector(-0.001,0.01); -} - - void update(PVector destination){ - //PVector mouse = new PVector(mouseX, mouseY); - PVector dir = PVector.sub(destination, location); - if(dir.mag() < 10.0){ - move = false; - } - else{ - move = true; - } - - dir.normalize(); - dir.mult(0.5); - acceleration = dir; - - if(move){ - velocity.add(acceleration); - } - else{ - velocity.set(0.0,0.0); - } - - //velocity.add(acceleration); - velocity.limit(topspeed); - location.add(velocity); - - } - - void display(){ - noStroke(); - fill(col); - ellipse(location.x, location.y, r, r); - } - - void checkEdges(){ - if (location.x > width){ - location.x = 0; - } else if(location.x < 0) { - location.x = width; - } - - if(location.y > height){ - location.y = 0; - } else if (location.y < 0) { - location.y = height; - } - - } -} \ No newline at end of file diff --git a/1_pollution/PSEQ1/slow_earthy/slow_earthy.pde b/1_pollution/PSEQ1/slow_earthy/slow_earthy.pde deleted file mode 100644 index 3e46924..0000000 --- a/1_pollution/PSEQ1/slow_earthy/slow_earthy.pde +++ /dev/null @@ -1,133 +0,0 @@ -private static boolean mode_kinect = true; - -Mover[] movers = new Mover[20]; - -//Kinect imports -import kinect4WinSDK.Kinect; -import kinect4WinSDK.SkeletonData; -Kinect kinect; -ArrayList bodies; - -void setup(){ - size(1440, 800, P3D); - background(0); - smooth(); - for(int i = 0; i < movers.length; i++){ - //int gray = int(random(255)); - movers[i] = new Mover(); - //movers[i].col = color(gray, gray, gray); - //movers[i].orig_col = movers[i].col; - } - kinect = new Kinect(this); - bodies = new ArrayList (); - - println("Converging PSEQ2"); - -} - -void draw(){ - noStroke(); - fill(0,20); - rect(0, 0, width, height); - - if(mode_kinect){ - //SkeletonData body; - //if body detected - if (bodies.size() != 0){ - int bodyIndex = bodies.size() - 1; - //for(SkeletonData body : bodies){ - SkeletonData body = bodies.get(bodyIndex); - //PVector body_pos = body.position; - //println("Body x, y:"); - //println(body.position.x); - //println(body.position.y); - updatePositionKinect(body); - //} - } - else{ - int delta = 60; - for(int i = 0; i < movers.length; i++){ - //movers[i].update(mouse_pos); - movers[i].checkEdges(); - movers[i].display(); - movers[i].topspeed = 0.5; - PVector goal = new PVector(random(movers[i].location.x-delta, movers[i].location.x+delta), random(movers[i].location.y-delta, movers[i].location.y+delta)); - movers[i].update(goal); - } - //noStroke(); - //noFill(); - //background(0); - } - } - else{ // if mouse and not kinect - PVector mouse_pos = new PVector(mouseX,mouseY); - for(int i = 0; i < movers.length; i++){ - movers[i].update(mouse_pos); - movers[i].checkEdges(); - movers[i].display(); - } - } -} - -//Kinect events - -void appearEvent(SkeletonData _s) -{ - if (_s.trackingState == Kinect.NUI_SKELETON_NOT_TRACKED) - { - return; - } - println("Body appeared!"); - synchronized(bodies) { - bodies.add(_s); - } -} - - -void disappearEvent(SkeletonData _s) -{ - println("Body gone!"); - synchronized(bodies) { - for (int i=bodies.size ()-1; i>=0; i--) - { - if (_s.dwTrackingID == bodies.get(i).dwTrackingID) - { - bodies.remove(i); - } - } - } -} - - -void moveEvent(SkeletonData _b, SkeletonData _a) -{ - if (_a.trackingState == Kinect.NUI_SKELETON_NOT_TRACKED) - { - return; - } - //println("Body moving!"); - synchronized(bodies) { - for (int i=bodies.size ()-1; i>=0; i--) - { - if (_b.dwTrackingID == bodies.get(i).dwTrackingID) - { - bodies.get(i).copy(_a); - break; - } - } - } -} - -void updatePositionKinect(SkeletonData body){ - //PVector body_pos = new PVector(body.position.x*width, body.position.y*height); - //PVector[] body_part_pos = body.skeletonPositions; - for(int i = 0; i < movers.length; i++){ - PVector pos = new PVector(body.skeletonPositions[i%body.skeletonPositions.length].x*width, body.skeletonPositions[i%body.skeletonPositions.length].y*height); - fill(0,0,127); - ellipse(pos.x, pos.y, 16, 20); - //movers[i].setRed(); - movers[i].update(pos); - movers[i].checkEdges(); - movers[i].display(); - } -} \ No newline at end of file