But what, I could do that 3 days after first learning Processing. I wanted a challenge that actually felt like a final project to me. 36 or so hours later, I ended up with four charts, three of which are interactive and immersive, and a menu-based interaction system.
Basically, paste these code snippets into various tabs of Processing and execute them. Alternatively download the zip file of the project from GitHub. Bearing in mind there's close to a thousand lines of code (over 900 at least), I'm going to post my YouTube video explaining it first.
2017HurricaneData.txt file:
Storm Name,Minimum Pressure,Max Wind Speed,Damage,Damage String,WikiBret,1007,50,2960000,$2.960.000,https://en.wikipedia.org/wiki/Tropical_Storm_Bret_(2017)Cindy,991,60,25000000,$25.000.000,https://en.wikipedia.org/wiki/Tropical_Storm_Cindy_(2017)Emily,1001,60,10000000,$10.000.000,https://en.wikipedia.org/wiki/Tropical_Storm_Emily_(2017)Franklin,981,85,15000000,$15.000.000,https://en.wikipedia.org/wiki/Hurricane_FranklinHarvey,937,130,125000000000,$125.000.000.000,https://en.wikipedia.org/wiki/Hurricane_HarveyIrma,914,180,77160000000,$77.160.000.000,https://en.wikipedia.org/wiki/Hurricane_IrmaJose,938,155,2840000,$2.840.000,https://en.wikipedia.org/wiki/Hurricane_Jose_(2017)Katia,972,105,3250000,$3.250.000,https://en.wikipedia.org/wiki/Hurricane_Katia_(2017)Maria,908,175,91610000000,$91.610.000.000,https://en.wikipedia.org/wiki/Hurricane_MariaNate,981,90,787000000,$787.000.000,https://en.wikipedia.org/wiki/Hurricane_NateOphelia,959,115,65300000,$65.300.000,https://en.wikipedia.org/wiki/Hurricane_Ophelia_(2017)
ACEdata.txt file
hurricaneYearData.txt file:Storm Name,ACE,WikiArlene,0.81,http://www.nhc.noaa.gov/data/tcr/AL012017_Arlene.pdfBret,0.5225,https://www.nhc.noaa.gov/data/tcr/AL022017_Bret.pdfCindy,0.81,https://www.nhc.noaa.gov/data/tcr/AL032017_Cindy.pdfDon,0.5225,http://www.nhc.noaa.gov/data/tcr/AL052017_Don.pdfEmily,1.8425,http://www.nhc.noaa.gov/data/tcr/AL062017_Emily.pdfFranklin,0.7675,http://www.nhc.noaa.gov/data/tcr/AL072017_Franklin.pdfGert,7.805,http://www.nhc.noaa.gov/data/tcr/AL082017_Gert.pdfHarvey,11.4425,http://www.nhc.noaa.gov/data/tcr/AL092017_Harvey.pdfIrma,64.8925,http://www.nhc.noaa.gov/data/tcr/AL112017_Irma.pdfJose,43.28,http://www.nhc.noaa.gov/data/tcr/AL122017_Jose.pdfKatia,6.055,http://www.nhc.noaa.gov/data/tcr/AL132017_Katia.pdfLee,17.925,http://www.nhc.noaa.gov/data/tcr/AL142017_Lee.pdfMaria,44.805,http://www.nhc.noaa.gov/data/tcr/AL152017_Maria.pdfNate,4.13,http://www.nhc.noaa.gov/data/tcr/AL162017_Nate.pdfOphelia,14.5225,http://www.nhc.noaa.gov/data/tcr/AL172017_Ophelia.pdfPhillipe,0.1225,https://www.nhc.noaa.gov/data/tcr/AL182017_Philippe.pdfRina,1.6625,http://www.nhc.noaa.gov/data/tcr/AL192017_Rina.pdf
Processing Code New Tab:Season,Tropical Depressions,Named Storms,Hurricanes,Category ≥2,Major hurricanes (Category≥3),Category≥4,Category 5,Strongest Storm,Wiki1967,29,8,6,2,1,1,1,Beulah,https://en.wikipedia.org/wiki/Hurricane_Beulah1968,14,8,5,0,0,0,0,Gladys,https://en.wikipedia.org/wiki/Hurricane_Gladys_(1968)1969,20,18,12,7,5,1,1,Camille,https://en.wikipedia.org/wiki/Hurricane_Camille1970,19,10,5,3,2,0,0,Celia,https://en.wikipedia.org/wiki/Hurricane_Celia1971,22,13,6,2,1,1,1,Edith,https://en.wikipedia.org/wiki/Hurricane_Edith_(1971)1972,19,7,3,1,0,0,0,Betty,https://en.wikipedia.org/wiki/1972_Atlantic_hurricane_season#Hurricane_Betty1973,24,8,4,1,1,0,0,Ellen,https://en.wikipedia.org/wiki/1973_Atlantic_hurricane_season#Hurricane_Ellen1974,21,11,4,3,2,1,0,Carmen,https://en.wikipedia.org/wiki/Hurricane_Carmen1975,23,9,6,5,3,1,0,Gladys,https://en.wikipedia.org/wiki/Hurricane_Carmen1976,23,10,6,4,2,0,0,Belle,https://en.wikipedia.org/wiki/Hurricane_Belle_(1976)1977,16,6,5,1,1,1,1,Anita,https://en.wikipedia.org/wiki/Hurricane_Anita1978,24,12,5,3,2,2,0,Greta,https://en.wikipedia.org/wiki/Hurricane_Greta-Olivia1979,26,9,5,3,2,2,1,David,https://en.wikipedia.org/wiki/Hurricane_David1980,15,11,5,5,2,1,1,Allen,https://en.wikipedia.org/wiki/Hurricane_Allen1981,22,12,7,4,3,1,0,Harvey,https://en.wikipedia.org/wiki/1981_Atlantic_hurricane_season#Hurricane_Harvey1982,9,6,2,1,1,1,0,Debby,https://en.wikipedia.org/wiki/Hurricane_Debby_(1982)1983,7,4,3,1,1,0,0,Alicia,https://en.wikipedia.org/wiki/Hurricane_Alicia1984,20,13,5,2,1,1,0,Diana,https://en.wikipedia.org/wiki/Hurricane_Diana_(1984)1985,14,11,7,3,3,1,0,Gloria,https://en.wikipedia.org/wiki/Hurricane_Gloria1986,10,6,4,1,0,0,0,Earl,https://en.wikipedia.org/wiki/1986_Atlantic_hurricane_season#Hurricane_Earl1987,14,7,3,1,1,0,0,Emily,https://en.wikipedia.org/wiki/Hurricane_Emily_(1987)1988,19,12,5,3,3,3,1,Gilbert,https://en.wikipedia.org/wiki/Hurricane_Gilbert1989,15,11,7,4,2,2,1,Hugo,https://en.wikipedia.org/wiki/Hurricane_Hugo1990,16,14,8,2,1,0,0,Gustav,https://en.wikipedia.org/wiki/Hurricane_Gustav_(1990)1991,12,8,4,3,2,1,0,Claudette,https://en.wikipedia.org/wiki/1991_Atlantic_hurricane_season#Hurricane_Claudette1992,10,7,4,3,1,1,1,Andrew,https://en.wikipedia.org/wiki/Hurricane_Andrew1993,10,8,4,2,1,0,0,Emily,https://en.wikipedia.org/wiki/Hurricane_Emily_(1993)1994,12,7,3,1,0,0,0,Florence,https://en.wikipedia.org/wiki/Hurricane_Florence_(1994)1995,21,19,11,8,5,3,0,Opal,https://en.wikipedia.org/wiki/Hurricane_Opal1996,13,13,9,6,6,2,0,Edouard,https://en.wikipedia.org/wiki/Hurricane_Edouard_(1996)1997,9,8,3,1,1,0,0,Erika,https://en.wikipedia.org/wiki/Hurricane_Erika_(1997)1998,14,14,10,7,3,2,1,Mitch,https://en.wikipedia.org/wiki/Hurricane_Mitch1999,16,12,8,8,5,5,0,Floyd,https://en.wikipedia.org/wiki/Hurricane_Floyd2000,19,15,8,4,3,2,0,Keith,https://en.wikipedia.org/wiki/Hurricane_Keith2001,17,15,9,5,4,2,0,Michelle,https://en.wikipedia.org/wiki/Hurricane_Michelle2002,14,12,4,3,2,1,0,Isidore,https://en.wikipedia.org/wiki/Hurricane_Isidore2003,21,16,7,4,3,2,1,Isabel,https://en.wikipedia.org/wiki/Hurricane_Isabel2004,16,15,9,7,6,4,1,Ivan,https://en.wikipedia.org/wiki/Hurricane_Ivan2005,31,28,15,8,7,5,4,Wilma,https://en.wikipedia.org/wiki/Hurricane_Wilma2006,10,10,5,2,2,0,0,Gordon,https://en.wikipedia.org/wiki/Hurricane_Gordon_(2006)2007,17,15,6,2,2,2,2,Dean,https://en.wikipedia.org/wiki/Hurricane_Dean2008,17,16,8,6,5,4,0,Ike,https://en.wikipedia.org/wiki/Hurricane_Ike2009,11,9,3,3,2,1,0,Bill,https://en.wikipedia.org/wiki/Hurricane_Bill_(2009)2010,21,19,12,9,5,4,0,Igor,https://en.wikipedia.org/wiki/Hurricane_Igor2011,20,19,7,4,4,2,0,Ophelia,https://en.wikipedia.org/wiki/Hurricane_Ophelia_(2011)2012,19,19,10,5,2,0,0,Sandy,https://en.wikipedia.org/wiki/Hurricane_Sandy2013,15,14,2,0,0,0,0,Humberto,https://en.wikipedia.org/wiki/2013_Atlantic_hurricane_season#Hurricane_Humberto2014,9,8,6,3,2,1,0,Gonzalo,https://en.wikipedia.org/wiki/Hurricane_Gonzalo2015,12,11,4,2,2,1,0,Joaquin,https://en.wikipedia.org/wiki/Hurricane_Joaquin2016,16,15,7,4,4,2,1,Matthew,https://en.wikipedia.org/wiki/Hurricane_Matthew2017,18,17,10,8,6,4,2,Maria,https://en.wikipedia.org/wiki/Hurricane_Maria2018,16,15,8,5,2,2,1,Michael,https://en.wikipedia.org/wiki/Hurricane_Michael
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 | //Initializes the menu. boolean globalMenu = true; boolean globalLine = false; boolean globalScatter = false; boolean globalPie = false; boolean globalBar = false; boolean globalBack = false; //End of menu initialization //Initializes the line chart. Table hurricaneYearData; ArrayList<HurricaneYearPoints> hurricaneSeason; //End of line chart initialization. //Initializes the scatter plot. Table hurricane2017; ArrayList<Hur2017Plot> hur2017Points; //End of scatter plot initialization. //Initializes the bar graph. Table aceData; ArrayList<ACEBar> aceArray; //End of bar graph initialization. void setup() { size(800, 600); //Initializes the ArrayList and table for the line chart. hurricaneYearData = loadTable("hurricaneYearData.csv", "header"); hurricaneSeason = new ArrayList<HurricaneYearPoints>(); plotHYD(); //This is necessary to pre-load the data graphically. //End of initialization of the line chart. //Initializes the ArrayList and table for the scatter plot. hurricane2017 = loadTable("2017HurricaneData.csv", "header"); hur2017Points = new ArrayList<Hur2017Plot>(); plotHurricane2017(); // This is necessary to pre-load the data graphically. //End of initialization of the scatter plot. //Initializes the ArrayList and table for the bar graph. aceData = loadTable("ACEdata.csv", "header"); aceArray = new ArrayList<ACEBar>(); plotACEData(); // This is necessary to pre-load the data graphically. //End of initialization of the bar graph. } void draw() { // These act as buttons. If it is on a certain window, then execute that window's code. // All code is structured as simple function calls so that the draw function looks tidy. if (globalMenu == true) { //The menu animationDraw(); buttonLine(); buttonScatter(); buttonPie(); buttonBar(); } if (globalLine == true) { //The line chart drawLineGraphSpecs(); drawHYD(); backButton(); // A universal back button that acts as the "Menu" button. It is in all charts. } if (globalScatter == true) { //The scatter plot drawScatterPlotSpecs(); drawHurricane2017(); drawScatterLabels2(); backButton(); } if (globalPie == true) { // The unsatisfactory pie chart. It was a pain. pieChart(300, majHurData); backButton(); } if (globalBar == true) { // The bar graph. drawACEDetails(); plotACEData(); backButton(); drawACELabels(); } } void mouseClicked() { //Since Processing only has one mouseClick function, I have to use if/then statements. if (globalMenu == true) { // If we are on the menu if (clickButtonLine() == true) { // If the line graph button is clicked globalMenu = false; // Set the menu to false and line graph to true. globalLine = true; globalScatter = false; globalPie = false; globalBar = false; } if (clickButtonScatter() == true) { // If the scatter plot button is clicked globalMenu = false; globalLine = false; globalScatter = true; globalPie = false; globalBar = false; } if (clickButtonPie() == true) { // If the pie chart button is clicked globalMenu = false; globalLine = false; globalScatter = false; globalPie = true; globalBar = false; } if (clickButtonBar() == true) { // If the bar graph button is clicked globalMenu = false; globalLine = false; globalScatter = false; globalPie = false; globalBar = true; } } if (globalLine == true) { // Handles the mouse events for the line graph. for (int i = 0; i <=51; i++) { HurricaneYearPoints hurricanes = hurricaneSeason.get(i); float mouseDist = dist(hurricanes.thisYear, hurricanes.thisYearQuant, mouseX, mouseY); if (mouseDist <= 5) { link(hurricanes.hurWiki); } } } if (globalScatter == true) { // Handles the mouse events for the scatter plot. for (int i = 0; i <=10; i++) { Hur2017Plot hurricane2017 = hur2017Points.get(i); float hur2017Dist = dist(hurricane2017.logDamage, hurricane2017.wind, mouseX, mouseY); if ((hur2017Dist <= hurricane2017.pressure)) { link(hurricane2017.hurricaneURL); } } } if (globalBar == true) { // Handles the mouse events for the bar graph for (int i = 0; i <=16; i++) { ACEBar ace2017 = aceArray.get(i); float mxLower = ace2017.posX; float myLower = height - 75; float mxHigher = ace2017.posX + 30; float myHigher = -ace2017.mapACE + height - 75; if (mouseX >= mxLower && mouseX <= mxHigher && mouseY <= myLower && mouseY >= myHigher) { link(ace2017.aceWiki); } } } // The back button. If it's clicked and any one of the graphs are drawn, then it'll access the menu. if (clickBackButton() == true && (globalLine == true || globalScatter == true || globalPie == true || globalBar == true)) { globalMenu = true; globalLine = false; globalScatter = false; globalPie = false; globalBar = false; } } |
New tab
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 | void buttonLine () { //Draws the aesthetic of the line graph button. noStroke(); fill(230); shapeMode(CENTER); rect(50, height/2-90, 300, 50, 20); textAlign(CENTER, CENTER); textSize(17); fill(0); text("Hurricane Frequency 1967-2018", 200, height/2-65); } boolean clickButtonLine() { // The functional line graph button. int mx = mouseX ; int my = mouseY ; int ylower = height/2-40 ; int yhigher = height/2-90 ; println ( "ylower=" + ylower + ",yhigher=" + yhigher ) ; println ( "mx = " + mx + ", my = " + my ) ; if (mx <= 350 && mx >= 50 && my >= yhigher && my <= ylower) { return true; } else { return false; } } void buttonScatter () { // Draws the aesthetic of the scatter plot button. noStroke(); fill(230); shapeMode(CENTER); rect(50, height/2-30, 300, 50, 20); textAlign(CENTER, CENTER); textSize(17); fill(0); text("2017 Costly Hurricanes", 200, height/2-5); } boolean clickButtonScatter() { // The functional scatter plot button. int mx = mouseX ; int my = mouseY ; int ylower = height/2+20 ; int yhigher = height/2-30 ; println ( "y lower=" + ylower + ",y higher=" + yhigher ) ; println ( "m x = " + mx + ", m y = " + my ) ; if (mx <= 350 && mx >= 50 && my >= yhigher && my <= ylower) { println("true"); return true; } else { return false; } } void buttonPie () { // Draws the aesthetic of the pie chart button. noStroke(); fill(230); shapeMode(CENTER); rect(50, height/2+30, 300, 50, 20); textAlign(CENTER, CENTER); textSize(17); fill(0); text("2016-2018 Major Hurricane", 200, height/2+45); text("Relative Damages", 200, height/2+60); } boolean clickButtonPie() { // The functional pie chart button. int mx = mouseX ; int my = mouseY ; int ylower = height/2+80 ; int yhigher = height/2+30 ; println ( "y lower=" + ylower + ",y higher=" + yhigher ) ; println ( "m x = " + mx + ", m y = " + my ) ; if (mx <= 350 && mx >= 50 && my >= yhigher && my <= ylower) { println("true"); return true; } else { return false; } } void buttonBar () { // Draws the aesthetic of the bar graph button. noStroke(); fill(230); shapeMode(CENTER); rect(50, height/2+90, 300, 50, 20); textAlign(CENTER, CENTER); textSize(17); fill(0); text("2017 Accumulated Cyclone Energy", 200, height/2+115); } boolean clickButtonBar() { // The functional bar graph button. int mx = mouseX ; int my = mouseY ; int ylower = height/2+140 ; int yhigher = height/2+90 ; println ( "y lower=" + ylower + ",y higher=" + yhigher ) ; println ( "m x = " + mx + ", m y = " + my ) ; if (mx <= 350 && mx >= 50 && my >= yhigher && my <= ylower) { println("true"); return true; } else { return false; } } void backButton() { // Draws the aesthetic of the back button fill(0); stroke(100); rect(10, 10, 30, 30); fill(255); textAlign(CENTER, CENTER); textSize(20); text("<", 25, 20); } boolean clickBackButton() { // The functional back button int mx = mouseX ; int my = mouseY ; int ylower = 40 ; int yhigher = 10 ; println ( "y lower=" + ylower + ",y higher=" + yhigher ) ; println ( "m x = " + mx + ", m y = " + my ) ; if (mx <= 40 && mx >= 10 && my >= yhigher && my <= ylower) { println("true"); return true; } else { return false; } } void animationDraw() { // This whole section just draws the menu aesthetics. background(200); noStroke(); fill(255, 255, 0); float cloudCX = map(mouseX, 0, width, -100, 900); float cloudCY = map(mouseY, 0, height, 100, 500); fill(100); ellipse(cloudCX, cloudCY, 75, 75); ellipse(cloudCX+30, cloudCY, 100, 100); ellipse(cloudCX+60, cloudCY, 75, 75); ellipse((cloudCX/2), cloudCY-50, 75, 75); ellipse((cloudCX/2)+30, cloudCY-50, 100, 100); ellipse((cloudCX/2)+60, cloudCY-50, 75, 75); ellipse((cloudCX/2*3), cloudCY+200, 75, 75); ellipse((cloudCX/2*3)+30, cloudCY+200, 100, 100); ellipse((cloudCX/2*3)+60, cloudCY+200, 75, 75); ellipse((cloudCX-300), cloudCY+300, 75, 75); ellipse((cloudCX-300)+30, cloudCY+300, 100, 100); ellipse((cloudCX-300)+60, cloudCY+300, 75, 75); // float cloudAX = map(mouseX, 0, width, 300, 500); float cloudAY = map(mouseY, 0, height, 200, 230); fill(140); ellipse(cloudAX, cloudAY, 75, 75); ellipse(cloudAX+30, cloudAY, 100, 100); ellipse(cloudAX+60, cloudAY, 75, 75); ellipse((cloudAX/2), cloudAY-50, 75, 75); ellipse((cloudAX/2)+30, cloudAY-50, 100, 100); ellipse((cloudAX/2)+60, cloudAY-50, 75, 75); ellipse((cloudAX/2*3), cloudAY+200, 75, 75); ellipse((cloudAX/2*3)+30, cloudAY+200, 100, 100); ellipse((cloudAX/2*3)+60, cloudAY+200, 75, 75); ellipse((cloudAX-300), cloudAY+300, 75, 75); ellipse((cloudAX-300)+30, cloudAY+300, 100, 100); ellipse((cloudAX-300)+60, cloudAY+300, 75, 75); // fill(180); float cloudBX = map(mouseX, 0, width, -200, 1000); float cloudBY = map(mouseY, 0, height, 300, 350); ellipse((cloudBX-300), cloudBY+300, 200, 200); ellipse((cloudBX-300)+100, cloudBY+300, 250, 250); ellipse((cloudBX-300)+200, cloudBY+300, 200, 200); ellipse((cloudBX/2-400), cloudBY-300, 200, 200); ellipse((cloudBX/2-400)+100, cloudBY-300, 250, 250); ellipse((cloudBX/2-400)+200, cloudBY-300, 200, 200); stroke(100, 150, 255); float x1 = random (0, width); float y1 = random (0, height); float x2 = random (0, width); float y2 = random (0, height); float x3 = random (0, width); float y3 = random (0, height); float x4 = random (0, width); float y4 = random (0, height); line(x1, y1, x1-50, y1-10); line(x2, y2, x2-50, y2-10); line(x3, y3, x3-50, y3-10); line(x4, y4, x4-50, y4-10); noStroke(); fill(0); textSize(60); textAlign(CENTER); text("Hurricane Data", width-225, height-300); text("Visualization", width-225, height-200); } |
New tab
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 | class ACEBar { // Defines the class for the bar graph. float aceValue; float mapACE; String hurr2017Name; String aceWiki; float posX; // Passes in the constructor arguments. ACEBar(float tempACEValue, float tempMapACE, String tempHurr2017Name, String tempACEWiki, float tempPosX) { aceValue = tempACEValue; mapACE = tempMapACE; hurr2017Name = tempHurr2017Name; aceWiki = tempACEWiki; posX = tempPosX; } void makeBar() { // Draws the actual data-containing portion of the graph. shapeMode(BOTTOM); fill(100, 100, 255); strokeWeight(3); stroke(0, 0, 255); rect(posX, height-75, 30, -mapACE ); } void makeBarLabel() { // Handles the mouseover event. if (mouseX >= posX && mouseX <= posX+30 && mouseY <= height-75 && mouseY >= -mapACE+height-75) { fill(255, 0, 0); textSize(25); textAlign(CENTER, BOTTOM); text(hurr2017Name + " ACE: " + aceValue, posX+15, -mapACE+(height-75)); } } } void drawACEDetails() { //Draws the window and the grid. background(100, 150, 255); fill(0); rect(10, 50, 775, 540); fill(255); stroke(100); rect(75, 100, 650, 450); int initi = 0; float inity = 525; int labelY = 0; while (initi <= 8) { stroke(150); strokeWeight(1); line(75, inity, 725, inity); textSize(15); text(labelY, 65, inity); inity -= 50; initi++; labelY += 8; } } void drawACELabels() { // Handles the labels textAlign(CENTER, CENTER); textSize(37); fill(255); text("2017 ACE", width/2, 75); textSize(17); text("Accumulated Cyclone Energy (ACE) is a measure of overall hurricane intensity.", width/2, 10); text("Click column for detailed report for the cyclone.", width/2, 30); textSize(30); text("2017 Atlantic Cyclones", width/2, 565); textSize(35); rotate(-PI/2); text("Accumulated Cyclone Energy", -325, 30); } void plotACEData() { // The part that actually processes the data. float posX = 100.0; for (TableRow row : aceData.rows()) { String hurr2017Name = row.getString("Storm Name"); float hurr2017ACE = row.getFloat("ACE"); String hurr2017Wiki = row.getString("Wiki"); float mapACE = map(hurr2017ACE, 0, 65, 0, 400); aceArray.add(new ACEBar(hurr2017ACE, mapACE, hurr2017Name, hurr2017Wiki, posX)); posX += 35.0; } for (int i=0; i<= 16; i++) { ACEBar ace2017 = aceArray.get(i); ace2017.makeBar(); } for (int i=0; i<= 16; i++) { ACEBar ace2017 = aceArray.get(i); ace2017.makeBarLabel(); } } |
New tab
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 | class HurricaneYearPoints { // Defines the class for the line graph. float thisYear; float thisYearQuant; float previousYear; float previousYearQuant; String hurricaneName; String hurWiki; // Passes in the constructor arguments. HurricaneYearPoints(String tempHurWiki, float tempThisYear, float tempThisYearQuant, float tempPreviousYear, float tempPreviousYearQuant, String tempHurricaneName) { thisYear = tempThisYear; thisYearQuant = tempThisYearQuant; previousYear = tempPreviousYear; previousYearQuant = tempPreviousYearQuant; hurricaneName = tempHurricaneName; hurWiki = tempHurWiki; } void makeLine() { // Draws the actual line and a circle to make the points clearer. stroke(0, 100, 255); strokeWeight(2); line(previousYear, previousYearQuant, thisYear, thisYearQuant); fill(0, 255, 0); ellipse(thisYear, thisYearQuant, 10, 10); } void makeLabel() { // Handles the mouseover event for the points. fill(255, 0, 0); float mouseDist = dist(thisYear, thisYearQuant, mouseX, mouseY); if ( mouseDist <= 5) { textSize(20); textAlign(RIGHT); text(hurricaneName, thisYear, thisYearQuant-30); textAlign(LEFT); text(int(map(thisYear, 50, width-50, 1967, 2018)), thisYear+5, thisYearQuant-30); } } } void plotHYD() { //The part that actually handles the data for the line graph. It doesn't draw it to the screen. float previousYearSeason = 1967; float previousNamedStorms = 8; for (TableRow row : hurricaneYearData.rows()) { float hurricaneYearSeason = row.getFloat("Season"); float namedStorms = row.getFloat("Named Storms"); String strongestStorm = row.getString("Strongest Storm"); String yearWiki = row.getString("Wiki"); float newhurricaneYearSeason = map(hurricaneYearSeason, 1967, 2018, 50, width-50); float newnamedStorms = map(namedStorms, 0, 28, height-50, 200); float newpreviousYearSeason = map(previousYearSeason, 1967, 2018, 50, width-50); float newpreviousNamedStorms = map(previousNamedStorms, 0, 28, height-50, 200); hurricaneSeason.add(new HurricaneYearPoints(yearWiki, newhurricaneYearSeason, newnamedStorms, newpreviousYearSeason, newpreviousNamedStorms, strongestStorm)); previousYearSeason = hurricaneYearSeason; previousNamedStorms = namedStorms; } //End of Hurricane Year Data Line Graph draw portion. for (int i=0; i<= 51; i++) { HurricaneYearPoints hurricanes = hurricaneSeason.get(i); hurricanes.makeLabel(); hurricanes.makeLine(); } } void drawHYD() { // Actually draws it to the screen. plotHYD(); for (int i=0; i<= 51; i++) { HurricaneYearPoints hurricanes = hurricaneSeason.get(i); hurricanes.makeLabel(); hurricanes.makeLine(); } } void drawLineGraphSpecs() { // Draws the labeling of the code. background(100, 150, 255); stroke(0, 255, 255); fill(0); rect(10, 75, width-20, height-85); fill(255); rect(50, 150, width-100, height-200); int initX = 50; int initY = height-50; int i = 0; int j = 0; int xMark = 0; int yMark = 1967; strokeWeight(1); while (i <= 12) { while (j <=8) { stroke(150); line(50, initY, width-50, initY); initY = initY - 50; j++; textAlign(CENTER); textSize(20); fill(255); text(xMark, width-30, initY+50); xMark = xMark + 4; } stroke(200); line(initX, 150, initX, height-50); initX = initX+(width-100)/13+2; i++; textAlign(CENTER, CENTER); textSize(15); fill(255); text(yMark, initX-50, height-42); yMark = yMark + 4; } text(2018, width-50, height-42); textSize(20); text("Year", width/2, height-25); pushMatrix(); rotate(-PI/2); translate(-375, -275); text("Named Storms Per Season", 20, height/2); popMatrix(); textSize(35); textAlign(CENTER, CENTER); text("Hurricane Frequency In The Satellite Era", width/2, 110); textSize(20); text("Mouse over point for more details.", width/2, 25); text("Click on point to learn more.", width/2, 50); } |
New tab
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | String [][] majHurData = { // Data is simple enough to not need a csv and works better as an array over a table {"Harvey", "125", "https://en.wikipedia.org/wiki/Hurricane_Harvey"}, {"Matthew", "16.47", "https://en.wikipedia.org/wiki/Hurricane_Matthew"}, {"Irma", "77.16", "https://en.wikipedia.org/wiki/Hurricane_Irma"}, {"Maria", "91.61", "https://en.wikipedia.org/wiki/Hurricane_Maria"}, {"Michael", "25.1", "https://en.wikipedia.org/wiki/Hurricane_Michael"}, }; void pieChart(float diameter, String [][] data) { // This section is a modified version of the //code in the documentation on pie charts. background(100, 150, 255); fill(0); rect(width/2-250, height/2-250, 500, 500); textAlign(CENTER, CENTER); textSize(25); fill(255); text("Relative Damages of Devastating ", width/2, height/2-235); text("Hurricanes (2016-2018)", width/2, height/2-205); text("This is a static graphic.", width/2, 30); float lastAngle = 0; float totalDam = 0; for (int i = 0; i < data.length; i++) { totalDam = totalDam + float(majHurData[i][1]); } for (int i = 0; i < data.length; i++) { float dataGreen = map(i, 0, data.length, 150, 255); float dataRed = map(i, 0, data.length, 50, 255); float dataBlue = map(i, 0, data.length, 200, 255); float damAngle = (float(data[i][1])/totalDam)*360; fill(dataRed, dataGreen, dataBlue); arc(width/2, height/2, diameter, diameter, lastAngle, lastAngle+radians(damAngle)); lastAngle += radians(damAngle); pushMatrix(); translate(width/2, height/2); float xPos =(200 * cos(lastAngle)); float yPos =(200 * sin(lastAngle)); float textGreen = map(i, 0, data.length, 150, 255); float textRed = map(i, 0, data.length, 50, 255); float textBlue = map(i, 0, data.length, 200, 255); fill(textRed, textGreen, textBlue); textSize(20); textAlign(CENTER, CENTER); text(data[i][0], xPos, yPos); popMatrix(); } } |
New tab
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 | class Hur2017Plot { // Defines the class for the scatter graph. float wind; float logDamage; float pressure; float unmapWind; String hurricaneURL; String hurricaneName; String damageString; // Passing in the constructor arguments. Hur2017Plot(String tempDamageString, float tempUnmapWind, float tempWind, float tempLogDamage, float tempPressure, String tempURL, String tempName) { unmapWind = tempUnmapWind; wind = tempWind; logDamage = tempLogDamage; pressure = tempPressure; hurricaneURL = tempURL; hurricaneName = tempName; damageString = tempDamageString; } void plotHurCircle() { // Plots the actual circle and defines its color. if (unmapWind >= 157.0) { stroke(180, 0, 0); fill(255, 20, 0); } else if (unmapWind >= 130.0) { stroke(255, 80, 0); fill(255, 100, 0); } else if (unmapWind >= 111.0) { stroke(255, 120, 0); fill(255, 150, 0); } else if (unmapWind >= 96.0) { stroke(255, 180, 70); fill(255, 200, 100); } else if (unmapWind >= 74.0) { stroke(255, 200, 180); fill(255, 255, 200); } else if (unmapWind < 74.0) { stroke(200, 255, 255); fill(0, 255, 255); } shapeMode(CENTER); textSize(12); textAlign(CENTER, CENTER); ellipse(logDamage, wind, pressure, pressure); fill(0); text(hurricaneName, logDamage, wind-pressure/2-5); } void hurInfoBox() { // Handles the mouseover event for each data point. float hur2017Dist = dist(logDamage, wind, mouseX, mouseY); int unmapPressure = int(map(pressure, 60, 10, 908, 1007)); if (hur2017Dist <= pressure/2) { fill(255); rect(width-485, 160, 230, 230); textAlign(LEFT, BOTTOM); textSize(13); fill(0); text("Name: " + hurricaneName, width-475, 190); text("Min Pressure: " + unmapPressure + "mbar", width-475, 220); text("Damage Cost: " + damageString, width-475, 250); if (unmapWind >= 157.0) { text("Wind Speed: " + int(unmapWind) + "mph (Category 5)", width-475, 280); } else if (unmapWind >= 130.0) { text("Wind Speed: " + int(unmapWind) + "mph (Category 4)", width-475, 280); } else if (unmapWind >= 111.0) { text("Wind Speed: " + int(unmapWind) + "mph (Category 3)", width-475, 280); } else if (unmapWind >= 96.0) { text("Wind Speed: " + int(unmapWind) + "mph (Category 2)", width-475, 280); } else if (unmapWind >= 74.0) { text("Wind Speed: " + int(unmapWind) + "mph (Category 1)", width-475, 280); } else if (unmapWind < 74.0) { text("Wind Speed: " + int(unmapWind) + "mph (Tropical Storm)", width-475, 280); } textSize(11); text("Click for more info. Wind speed is", width-475, 320); text("represented as max sustained gust", width-475, 340); text("(over one minute long). Larger circles", width-475, 360); text("represent lower barometric pressure.", width-475, 380); } } } void plotHurricane2017() { // Handles the actual data processing. int damMapMin=150; int damMapMax=width-100; int windMapMin=height-100; int windMapMax=200; for (TableRow hur2017Row : hurricane2017.rows()) { String hurName = hur2017Row.getString("Storm Name"); String hurURL = hur2017Row.getString("Wiki"); String damString = hur2017Row.getString("Damage String"); float hurPressure = hur2017Row.getFloat("Minimum Pressure"); float maxWind = hur2017Row.getFloat("Max Wind Speed"); float hurDamage = hur2017Row.getFloat("Damage"); float logHurDamage = log(hurDamage); float mapLogHurDamage = map(logHurDamage, 14.85, 27.55, damMapMin, damMapMax); float mapHurPressure = map(hurPressure, 908, 1007, 60, 10); float mapMaxWind = map(maxWind, 50, 180, windMapMin, windMapMax); hur2017Points.add(new Hur2017Plot(damString, maxWind, mapMaxWind, mapLogHurDamage, mapHurPressure, hurURL, hurName)); } } void drawHurricane2017() { // The part that actually plots it to the screen. plotHurricane2017(); for (int i = 0; i <=10; i++) { Hur2017Plot hurricane2017 = hur2017Points.get(i); hurricane2017.plotHurCircle(); hurricane2017.hurInfoBox(); } } void drawScatterPlotSpecs() { // A two-part thing that draws the labels and box and stuff. background(100, 150, 255); stroke(100); fill(0); rect(25, 100, width-50, height-110); stroke(0); fill(255); rect(100, 150, width-250, height-225); int windMapMin=height-100; int windMapMax=200; float tropStorm = map(50, 50, 180, windMapMin, windMapMax); float cat1 = map(74, 50, 180, windMapMin, windMapMax); float cat2 = map(96, 50, 180, windMapMin, windMapMax); float cat3 = map(111, 50, 180, windMapMin, windMapMax); float cat4 = map(130, 50, 180, windMapMin, windMapMax); float cat5 = map(157, 50, 180, windMapMin, windMapMax); textAlign(RIGHT, CENTER); textSize(15); stroke(200); line(100, cat1, width-150, cat1); text("74", 95, cat1); line(100, cat2, width-150, cat2); text("96", 95, cat2); line(100, cat3, width-150, cat3); text("111", 95, cat3); line(100, cat4, width-150, cat4); text("130", 95, cat4); line(100, cat5, width-150, cat5); text("157", 95, cat5); textAlign(LEFT, CENTER); textSize(15); stroke(200, 255, 255); fill(0, 255, 255); rect(width-140, 250, 20, 20); text("Trop Storm", width-115, 260); stroke(255, 200, 180); fill(255, 255, 200); rect(width-140, 280, 20, 20); text("Category 1", width-115, 290); stroke(255, 180, 70); fill(255, 200, 100); rect(width-140, 310, 20, 20); text("Category 2", width-115, 320); stroke(255, 120, 0); fill(255, 150, 0); rect(width-140, 340, 20, 20); text("Category 3", width-115, 350); stroke(255, 80, 0); fill(255, 100, 0); rect(width-140, 370, 20, 20); text("Category 4", width-115, 380); stroke(180, 0, 0); fill(255, 20, 0); rect(width-140, 400, 20, 20); text("Category 5", width-115, 410); stroke(200); int counti = 0; int offsetY = 100; while (counti <= 5) { line(offsetY, 150, offsetY, height-75); counti++; offsetY = offsetY + (width-250)/6; } } void drawScatterLabels2() { // The other part because things were getting cluttered in the other function. int offsetY = (width-250)/6; textAlign(CENTER, TOP); fill(255); textSize(20); text("$1M", 100, height-75); text("$10M", 100+offsetY, height-75); text("$100M", 100+2*offsetY, height-75); text("$1B", 100+3*offsetY, height-75); text("$10B", 100+4*offsetY, height-75); text("$100B", 100+5*offsetY, height-75); text("$1T", 100+6*offsetY, height-75); textSize(30); text("Logarithmic Cost of Damage", 100+3*offsetY, height-55); pushMatrix(); rotate(-PI/2); translate(-350, 30); text("Wind Speed (mph)", 0, 0); popMatrix(); textSize(40); text("2017 Costly Atlantic Cyclones", width/2, 100); textSize(20); text("Mouse over circle for more details.", width/2, 25); text("Click circle to learn more.", width/2, 50); text("Bear in mind the x-axis is on a logarithmic scale.", width/2, 75); } |
Fantastic!
ReplyDelete