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 | ArrayList<Cube> cubes; // Calls the array of cubes. float wheelCount = 0; // Counts the number of scrolls in. float event = 0; // Detects a scroll in and stores it. float camXPos = 150.0; // Camera X Position, with initial view. float camYPos = -100.0; // Camera Y Position, with initial view. float camZPos = 100.0; // Camera Z Position, with initial view. void setup() { size(1280, 720, P3D); //Sets render mode to 3D OpenGL render mode. background(0); cubes = new ArrayList<Cube>(); //Defines cube array instance. println("Navigate the viewport with WASD and QE, and use the scroll wheel to zoom."); println("Press R to reset the view back to the default."); } void draw() { background(0); //Redraws background in order to prevent trails. //This section was an attempt to get the pivot point at the center of mass //of the cubes. It didn't work but it does something, so I'm keeping it. float xSum = 0; float ySum = 0; float zSum = 0; for (int i = 1; i <= 12; i++) { xSum = xSum + float(nbaData[i][16]); ySum = ySum +float(nbaData[i][17]); zSum = zSum +float(nbaData[i][18]); } //End of semi-useless section. //This section zooms in and out towards the origin. if (wheelCount > 0) { event = event + wheelCount*3; // Change the coefficient to change speed. camera(event+600, 0.0, 0.0, xSum, ySum, zSum, 0.0, 1.0, 0.0); //Previous line positions camera. Here's where the useless section //was supposed to do something. wheelCount = 0; } if (wheelCount <= 0) { event = event + wheelCount*3; // Change it here too to the same value. camera(event+600, 0, 0, -xSum, -ySum, -zSum, 0.0, 1.0, 0.0); //Previous line positions camera. Here's where the useless section //was supposed to do something. wheelCount = 0; } // End of zoom section. // This section defines keyboard navigation. The WASD and QE keys // navigate the viewport, albeit poorly. It does the job, though. if (keyPressed) { if (key == 'w' || key == 'W') { camXPos = camXPos + 0.01; } if (key == 's' || key == 'S') { camXPos = camXPos - 0.01; } if (key == 'a' || key == 'A') { camYPos = camYPos + 0.01; } if (key == 'd' || key == 'D') { camYPos = camYPos - 0.01; } if (key == 'q' || key == 'Q') { camZPos = camZPos + 0.01; } if (key == 'e' || key == 'E') { camZPos = camZPos - 0.01; } if (key == 'r' || key == 'R') { //Resets camera view to default. camXPos = 150.0; camYPos = -100.0; camZPos = 100.0; event = 0; } } rotateX(camXPos); //These are what actually rotate the view. rotateY(camYPos); rotateZ(camZPos); // End of keyboard nav section. colorMode(HSB, 100); //Sets color mode to HSB from RGB in order to allow easier // color cycling of the cubes. // The meat of the plotter. This is the most important part of the scatter plot. for (int i = 1; i <= 12; i++) { float xPos = float(nbaData[i][16]); float yPos = float(nbaData[i][17]); float zPos = float(nbaData[i][18]); float newXPos = map(xPos, 0, 1, 0, 300); float newYPos = map(yPos, 0, 1, 0, 300); float newZPos = map(zPos, 0, 1, 0, 300); float cubeHue = float(nbaData[i][3]); cubeHue = map(cubeHue, 21, 38, 1, 90); String fullName = nbaData[i][1]+ " " + nbaData[i][2]; String playerData = "Age: " + int(nbaData[i][3]) + " FG%: " + nbaData[i][16] + " 3P%: " + nbaData[i][17] + " FT%: " + nbaData[i][18]; cubes.add(new Cube(playerData, fullName, cubeHue, newXPos, newYPos, newZPos)); } // End of main plotting definer. // Calls the grid functions to draw them. First the plane grids, then the axes // information on top of them. drawXZGrid(); drawXYGrid(); drawYZGrid(); axes(); // The XY, XZ, YZ labeling may be incorrect to the corresponding grid, but // the code works and that's what's important. // This section actually draws the cubes that were previously plotted, as well // as their labelings. for (int i=0; i <=11; i++) { Cube c = cubes.get(i); c.makeCube(); c.makeText(); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | // This array was copied from the provided sketch because there's no point in // retyping the entire dataset, since that's not the point of this project. String [][] nbaData = { // Columns go across, rows go down. Each is numbered starting from 0 // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 /* 0 */ { "Rank", "PlayerFname", "PlayerLname", "Age", "Tm", "First", "PtsWon", "PtsMax", "Share", "G", "MP", "PTS", "TRB", "AST", "STL", "BLK", "FG%", "3P%", "FT%", "WS", "WS/48" }, /* 1 */ { "1", "Stephen", "Curry", "26.0", "GSW", "100.0", "1198.0", "1300", "0.922", "80", "32.7", "23.8", "4.3", "7.7", "2.0", "0.2", ".487", ".443", ".914", "15.7", ".288" }, /* 2 */ { "2", "James", "Harden", "25.0", "HOU", "25.0", "936.0", "1300", "0.720", "81", "36.8", "27.4", "5.7", "7.0", "1.9", "0.7", ".440", ".375", ".868", "16.4", ".265" }, /* 3 */ { "3", "LeBron", "James", "30.0", "CLE", "5.0", "552.0", "1300", "0.425", "69", "36.1", "25.3", "6.0", "7.4", "1.6", "0.7", ".488", ".354", ".710", "10.4", ".199" }, /* 4 */ { "4", "Russell", "Westbrook", "26.0", "OKC", "0.0", "352.0", "1300", "0.271", "67", "34.4", "28.1", "7.3", "8.6", "2.1", "0.2", ".426", ".299", ".835", "10.6", ".222" }, /* 5 */ { "5", "Anthony", "Davis", "21.0", "NOP", "0.0", "203.0", "1300", "0.156", "68", "36.1", "24.4", "10.2", "2.2", "1.5", "2.9", ".535", ".083", ".805", "14.0", ".274" }, /* 6 */ { "6", "Chris", "Paul", "29.0", "LAC", "0.0", "124.0", "1300", "0.095", "82", "34.8", "19.1", "4.6", "10.2", "1.9", "0.2", ".485", ".398", ".900", "16.1", ".270" }, /* 7 */ { "7", "LaMarcus", "Aldridge", "29.0", "POR", "0.0", "6.0", "1300", "0.005", "71", "35.4", "23.4", "10.2", "1.7", "0.7", "1.0", ".466", ".352", ".845", "8.6", ".165" }, /* 8 */ { "9T", "Marc", "Gasol", "30.0", "MEM", "0.0", "3.0", "1300", "0.002", "81", "33.2", "17.4", "7.8", "3.8", "0.9", "1.6", ".494", ".176", ".795", "10.2", ".182" }, /* 9 */ { "9T", "Blake", "Griffin", "25.0", "LAC", "0.0", "3.0", "1300", "0.002", "67", "35.2", "21.9", "7.6", "5.3", "0.9", "0.5", ".502", ".400", ".728", "9.0", ".183" }, /* 10 */ { "12T", "Tim", "Duncan", "38.0", "SAS", "0.0", "1.0", "1300", "0.001", "77", "28.9", "13.9", "9.1", "3.0", "0.8", "2.0", ".512", ".286", ".740", "9.6", ".207" }, /* 11 */ { "12T", "Kawhi", "Leonard", "23.0", "SAS", "0.0", "1.0", "1300", "0.001", "64", "31.8", "16.5", "7.2", "2.5", "2.3", "0.8", ".479", ".349", ".802", "8.6", ".204" }, /* 12 */ { "12T", "Klay", "Thompson", "24.0", "GSW", "0.0", "1.0", "1300", "0.001", "77", "31.9", "21.7", "3.2", "2.9", "1.1", "0.8", ".463", ".439", ".879", "8.8", ".172" } } ; |
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 | // This tab defines the bounding box in order to draw the various axes and labels. //This section draws the axes' labels. void axes() { stroke(100, 100, 100); fill(100, 0, 100); textMode(MODEL); // This allows us to manipulate the text as a 3D object. textSize(20); textAlign(CENTER, CENTER); //Aligns in exact center of text for better //aligning with axes. //Draws one set of axes labels text("20%", 60, -10, 0); text("40%", 120, -10, 0); text("60%", 180, -10, 0); text("80%", 240, -10, 0); text("100%", 300, -10, 0); //Draws another set of axes labels text("20%", -10, 60, 0); text("40%", -10, 120, 0); text("60%", -10, 180, 0); text("80%", -10, 240, 0); text("100%", -10, 300, 0); //Draws final set of axes labels text("20%", -10, 0, 60); text("40%", -10, 0, 120); text("60%", -10, 0, 180); text("80%", -10, 0, 240); text("100%", -10, 0, 300); // This section defines axes names. stroke(100, 100, 100); //Defines label color and size. strokeWeight(2); fill(16, 70, 100); textSize(20); //FT% axis label. pushMatrix(); rotateX(PI/2); rotateY(PI/2); rotateZ(-PI/2); translate(-150, -140, -147); text("Free Throw Percentage", 0, 150, 150); popMatrix(); //TP% axis label. pushMatrix(); rotateX(PI/2); rotateY(PI/2); rotateZ(0); translate(150, -140, -147); text("Three Point Percentage", 0, 150, 150); popMatrix(); //FG% axis label. pushMatrix(); rotateX(0); rotateY(0); rotateZ(0); translate(150, -140, -147); text("Field Goal Percentage", 0, 150, 150); popMatrix(); } //This section defines the grids. The code is a modified version of my // "aesthetic" program grid code which is why the variables are named as such. void drawXZGrid() { stroke(0, 100, 100); //Red Grid int xgridr = 0; int ygridr = 0; while (ygridr <= 300) { while (xgridr <= 300) { line(xgridr, 300, 0, xgridr, 0, 0); //Draws one set of lines xgridr = xgridr + 30; } line(0, ygridr, 0, 300, ygridr, 0); //Draws perpendicular set of lines ygridr = ygridr +30; } } void drawXYGrid() { stroke(80, 100, 100); //Blue grid int xgridr = 0; int ygridr = 0; while (ygridr <= 300) { while (xgridr <= 300) { line(0, xgridr, 0, 0, xgridr, 300); //Draws one set of lines. xgridr = xgridr + 30; } line(0, 300, ygridr, 0, 0, ygridr); //Draws perpendicular set of lines. ygridr = ygridr +30; } } void drawYZGrid() { stroke(30, 100, 100); //Green grid int xgridr = 0; int ygridr = 0; while (ygridr <= 300) { while (xgridr <= 300) { line(0, 0, xgridr, 300, 0, xgridr); //Draws one set of lines. xgridr = xgridr + 30; } line(ygridr, 0, 0, ygridr, 0, 300); //Draws perpendicular set of lines. ygridr = ygridr +30; } } |
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 | // This section defines the cube object, with parameters from the plotter. class Cube { float cubeColor; //These are the defined variables used in the cube object. float cubeXPos; float cubeYPos; float cubeZPos; String playerData; String playerName; Cube(String tempData, String tempName, float tempCubeColor, float tempCubeXPos, float tempCubeYPos, float tempCubeZPos) { playerData = tempData; // This takes the input information and passes playerName = tempName; // it into the cube object. cubeColor = tempCubeColor; cubeXPos = tempCubeXPos; cubeYPos = tempCubeYPos; cubeZPos = tempCubeZPos; } void makeCube() { // The part that actually defines an individual cube. pushMatrix(); translate(cubeXPos, cubeYPos, cubeZPos); //Translates cube to defined position. rotateY(frameCount/100.0); // This is just for aesthetic flair to make rotateX(frameCount/100.0); // the chart look more dynamic. It rotates rotateZ(frameCount/100.0); // each individual cube upon its local axis // because it's within a push/pop matrix. stroke(0); // Sets the stroke to black for contrast strokeWeight(2); colorMode(HSB); fill(cubeColor, 100, 100); // Cube color is the 4th dimension. // Red end of spectrum is younger, purple is older. box(5); // Actually draws the box. Change this value to change box size. popMatrix(); } void makeText() { // This section draws the info text since Processing lacks a // 3D cursor preventing adding mouseOver/mouseClick events. pushMatrix(); textMode(MODEL); // Locally defines text mode to a 3D model. noStroke(); textSize(10); textAlign(RIGHT); // Right aligns for better positioning. text(playerData, cubeXPos-10, cubeYPos+3, cubeZPos); textAlign(LEFT); // Left aligns for better positioning. text(playerName, cubeXPos+10, cubeYPos+3, cubeZPos); popMatrix(); } } |
1 2 3 4 5 6 7 | // This small section could've been appended to the main program but for // organization of other functions, I kept it separate. It just checks for // mouse scrolls in order to be used in the main program. void mouseWheel(MouseEvent event) { wheelCount = event.getCount(); } |
No comments:
Post a Comment