//---------------------------------------------- // Project: Soccer Monitoring // Author: Hao Chen // Version: 2.3 //---------------------------------------------- // time slot int index = 0; //totallength of time slot, current time, interval of display, framerate int totallen, totplayer = 30, time,val=1,frate=2; //position of timeline float timepos; //variable to determine weather mouse is on the particular button or timeline boolean mouseontime = false,mouseonframe = false, mouseonRestart = false, mouseonplay = false, playonoff = true; // color of play button int playcolor=255; //display player on and off //boolean[] mouseonplayer = new boolean[29], ponoff= new boolean[29]; //declare font PFont font; //convert gps number to player gersey and player name String[][] gps2jersey = new String[30][2]; //store every x,y coordinate into a 3D array (playerPos[playerID][timeIndex][x,y]) float[][][] playerPos = new float[30][1801][2]; //all the basestation position and position of 4 coordinates float[][] allBasePos = new float[8][2], cornarval = new float[4][2]; // cx1,cy1,cx2,cy2,cx3,cy3,cx4,cy4; // scale value to show on the PC screen, x axis margin, y axis margin int scaleval = 6, xoffset = 40, yoffset = 35; // correct player position float xcorrection = xoffset, ycorrection = yoffset/4; // bkground image PImage bkgnd; //============================================================================================================== //setup function will only called once void setup() { println("setup begin"); //initialize array to import data eg. ps01 use this convention to load data from the corresponding text file String[] cornar, flist, tmp, pieces; size(850, 740); // set window size font = loadFont("TheSans-Plain-12.vlw"); //set up fonts textFont(font); stroke(255); //import player data from .txt flist = loadStrings("flist.txt"); //flist contains all the file name e.g. p01.txt... //import each players coordinates for (int j = 0; j < flist.length; j++) { tmp = loadStrings(flist[j]); if (tmp == null) { playerPos[j][0][1] = -100.0; // set flag value -100.0 means there is not entry for this player println(playerPos[j][0][1] + " " + flist[j] + " do not exist"); }else { // println(flist[j] + " start " + "size" + flist.length + "x" + tmp.length); for (int i = 0; i < tmp.length; i++) { pieces = split(tmp[i], '\t'); playerPos[j][i][0] = float(pieces[0])*scaleval + xoffset - xcorrection; playerPos[j][i][1] = float(pieces[1])*scaleval + yoffset - ycorrection; } // println(playerPos[j][0][0] + " " + flist[j] + " done"); } totallen = 1801; } //import bkground data (soccer ground size) cornar = loadStrings("cornar.txt"); // GPS corodinate of 4 corner of soccer field for (int i = 0; i < cornar.length; i++){ pieces = split(cornar[i], '\t'); cornarval[i][0] = float(pieces[0])*scaleval + xoffset; cornarval[i][1] = float(pieces[1])*scaleval + yoffset; } //load all the gps to player mapping tmp = loadStrings("gps2jersey.csv"); for (int i = 0; i < totplayer; i++){ pieces = split(tmp[i], ','); // println(pieces); gps2jersey[i][0] = pieces[0]; gps2jersey[i][1] = pieces[1]; } // set all initial boolen val // for (int i = 0; i < 29; i++) { // mouseonplayer[i] = false; // ponoff[i] = true; // } //draw background // drawBkground(); // save("/data/bkground.tif"); // bkgnd = loadImage("bkground.tif"); } //============================================================================================================== //draw function will called every second (defaultframe rate = 1) void draw() { frameRate(frate); if (index >= totallen-1) val = 0; // Go to the next line for the next run through draw() index = index + val; timepos = (index/4); // rather than drawBkground(); and waste processing everytime draw bkground once then load the image every frame?? => failed drawBkground(); // image(bkgnd, 0, 0); playerpos(); transpose(); timeline(); fratechange(); playername(); } //draw background void drawBkground() { float conarArcRad = (cornarval[2][0]-cornarval[0][0])/20, centerCircleRad = (cornarval[2][0]-cornarval[0][0])/3.5; background(200); fill(0, 102, 0); stroke(255); rectMode(CORNER); rect(0,0,cornarval[3][0]+xoffset,cornarval[3][1]+yoffset); rect(cornarval[0][0],cornarval[0][1],cornarval[3][0]-xoffset,cornarval[3][1]-yoffset); noFill(); arc(cornarval[0][0], cornarval[0][1], conarArcRad, conarArcRad, 0, PI/2); arc(cornarval[2][0], cornarval[2][1], conarArcRad, conarArcRad, PI/2, PI); arc(cornarval[3][0], cornarval[3][1], conarArcRad, conarArcRad, PI, TWO_PI-PI/2); arc(cornarval[1][0], cornarval[1][1], conarArcRad, conarArcRad, TWO_PI-PI/2, TWO_PI); line(cornarval[0][0],(cornarval[3][1]+yoffset)/2,cornarval[3][0],(cornarval[3][1]+yoffset)/2); ellipse((cornarval[3][0]+xoffset)/2,(cornarval[3][1]+yoffset)/2,centerCircleRad,centerCircleRad); rectMode(CENTER); rect((cornarval[3][0]+xoffset)/2,cornarval[0][1]+conarArcRad/2,centerCircleRad,conarArcRad); rect((cornarval[3][0]+xoffset)/2,cornarval[3][1]-conarArcRad/2,centerCircleRad,conarArcRad); rect((cornarval[3][0]+xoffset)/2,cornarval[0][1]+conarArcRad/2*3,2*centerCircleRad,conarArcRad*3); rect((cornarval[3][0]+xoffset)/2,cornarval[3][1]-conarArcRad/2*3,2*centerCircleRad,conarArcRad*3); drawBasestation(); } //draw basestation void drawBasestation() { int stationsize = 5; //rxrange in meter float bx1,bx2,bx3,bx4,bx5,bx6,bx7,bx8,by1,by2,by3,by4,by5,by6,by7,by8; // position of basestations fill(25,12,0); stroke(255); bx3 = cornarval[0][0]-stationsize*2; by3 = (cornarval[3][1]+yoffset)/2; rect(bx3,by3,stationsize,stationsize); //b3 text("B3",cornarval[0][0]-30,(cornarval[3][1]+yoffset)/2); bx7 = cornarval[3][0]+stationsize*2; by7 = (cornarval[3][1]+yoffset)/2; rect(bx7,by7,stationsize,stationsize); //b7 text("B7",cornarval[3][0]+20,(cornarval[3][1]+yoffset)/2); bx5 = (cornarval[3][0]+xoffset)/2; by5 = cornarval[0][1]-stationsize*2; rect(bx5,by5,stationsize,stationsize); //b5 text("B5",(cornarval[3][0]+xoffset)/2-7,cornarval[0][1]-15); bx1 = (cornarval[3][0]+xoffset)/2; by1 = cornarval[3][1]+stationsize*2; rect(bx1,by1,stationsize,stationsize); //b10 text("B1",(cornarval[3][0]+xoffset)/2-10,cornarval[3][1]+25); bx4 = cornarval[0][0]-stationsize*2; by4 = ((cornarval[3][1]+yoffset)/2-cornarval[0][1])/2+yoffset; rect(bx4,by4,stationsize,stationsize); //b4 text("B4",cornarval[0][0]-30,((cornarval[3][1]+yoffset)/2-cornarval[0][1])/2+yoffset); bx6 = cornarval[3][0]+stationsize*2; by6 = ((cornarval[3][1]+yoffset)/2-cornarval[0][1])/2+yoffset; rect(bx6,by6,stationsize,stationsize); //b6 text("B6",cornarval[3][0]+20,((cornarval[3][1]+yoffset)/2-cornarval[0][1])/2+yoffset); bx2 = cornarval[0][0]-stationsize*2; by2 = (cornarval[3][1]-(cornarval[3][1]+yoffset)/2)/2+(cornarval[3][1]+yoffset)/2; rect(bx2,by2,stationsize,stationsize); //b2 text("B2",cornarval[0][0]-30,(cornarval[3][1]-(cornarval[3][1]+yoffset)/2)/2+(cornarval[3][1]+yoffset)/2); bx8 = cornarval[3][0]+stationsize*2; by8 = (cornarval[3][1]-(cornarval[3][1]+yoffset)/2)/2+(cornarval[3][1]+yoffset)/2; rect(bx8,by8,stationsize,stationsize); //b8 text("B8",cornarval[3][0]+20,(cornarval[3][1]-(cornarval[3][1]+yoffset)/2)/2+(cornarval[3][1]+yoffset)/2); allBasePos[0][0] = bx1; allBasePos[0][1] = by1; allBasePos[1][0] = bx2; allBasePos[1][1] = by2; allBasePos[2][0] = bx3; allBasePos[2][1] = by3; allBasePos[3][0] = bx4; allBasePos[3][1] = by4; allBasePos[4][0] = bx5; allBasePos[4][1] = by5; allBasePos[5][0] = bx6; allBasePos[5][1] = by6; allBasePos[6][0] = bx7; allBasePos[6][1] = by7; allBasePos[7][0] = bx8; allBasePos[7][1] = by8; // noFill(); // for (int i = 0; i < 8; i++){ // ellipse(allBasePos[i][0],allBasePos[i][1],rxRange*scaleval,rxRange*scaleval); // } } void transpose() { fill(30); //rewind rect text("Click to Restart", cornarval[3][0]+xoffset+30, cornarval[3][1]+yoffset+20-70); fill(0); text("Restart", cornarval[3][0]+xoffset+55, cornarval[3][1]+yoffset+20-50); fill(57,0,0); stroke(255); rect(cornarval[3][0]+xoffset+40, cornarval[3][1]+yoffset+20-50,20,20); if (mouseonRestart = overRect(cornarval[3][0]+xoffset+40,cornarval[3][1]+yoffset+20-50,20,20)) { stroke(255,255,0); rect(cornarval[3][0]+xoffset+40, cornarval[3][1]+yoffset+20-50,20,20); } //play pause rect text("Click to Play/Pause", cornarval[3][0]+xoffset+30, cornarval[3][1]+yoffset+20-120); if (playonoff == false) { fill(playcolor); text("Pause", cornarval[3][0]+xoffset+55, cornarval[3][1]+yoffset+20-100); } else { fill(playcolor,0,0); text("Play", cornarval[3][0]+xoffset+55, cornarval[3][1]+yoffset+20-100); } fill(playcolor,0,0); rect(cornarval[3][0]+xoffset+40, cornarval[3][1]+yoffset+20-100,20,20); if (mouseonplay = overRect(cornarval[3][0]+xoffset+40,cornarval[3][1]+yoffset+20-100,20,20)) { stroke(255,255,0); rect(cornarval[3][0]+xoffset+40, cornarval[3][1]+yoffset+20-100,20,20); } } //plot player position based on the data imported void playerpos() { strokeWeight(1); float x,y; int rxRange = 10; // for one team (15 GPS reserved) for (int i = 0; i < totplayer/2-1; i++) { if (playerPos[i][0][1] != -100) { if (index < totallen ) { // println("time = " + index + " " + allPlayerPos[i][index]); x = playerPos[i][index][0]; y = playerPos[i][index][1]; // println(x + " " + y); // print position for debug fill(203,10,10); stroke(0xFF); ellipse(x, y, 15, 15); noFill(); strokeWeight(0.5); stroke(153); //ellipse(x, y, rxRange*scaleval, rxRange*scaleval); fill(255); textSize(12); // text(i+1, x-3, y+4); // Gps number text(int(gps2jersey[i][0]), x-3, y+4); // player number //baseRx(x,y); //playerRx(x,y); } } } // for another team (15 GPS reserved) for (int i = totplayer/2; i < totplayer-1; i++) { if (playerPos[i][0][1] != -100) { if (index < totallen ) { // println("time = " + index + " " + allPlayerPos[i][index]); x = playerPos[i][index][0]; y = playerPos[i][index][1]; // println(x + " " + y); // print position for debug fill(10,255,5); stroke(0xFF); ellipse(x, y, 15, 15); noFill(); strokeWeight(0.5); stroke(153); //ellipse(x, y, rxRange*scaleval, rxRange*scaleval); fill(0); textSize(12); // text(i+1, x-3, y+4); // Gps number text(int(gps2jersey[i][0]), x-3, y+4); // player number //baseRx(x,y); //playerRx(x,y); } } } } void baseRx(float x, float y) { int rxRange = 40; noFill(); for (int i = 0; i < 8; i++) { strokeWeight(0.5); if (overCircle(allBasePos[i][0], allBasePos[i][1], rxRange*scaleval, x, y)) { stroke(204, 102, 0); ellipse(allBasePos[i][0],allBasePos[i][1],rxRange*scaleval,rxRange*scaleval); } } } //void playerRx(float x, float y) { // float ax, ay; // int rxRange = 10; // noFill(); // for (int i = 0; i < allPlayerPos.length-1; i++) { // if (allPlayerPos[i][0] != "NA") { // String[] pieces = split(allPlayerPos[i][index], '\t'); // ax = float(pieces[0])*scaleval + xoffset - xcorrection; // ay = float(pieces[1])*scaleval + yoffset - ycorrection; // strokeWeight(0.5); // if (overCircle(x, y, rxRange*scaleval, ax, ay)) { // stroke(0x12E9FF); // ellipse(x,y,rxRange*scaleval,rxRange*scaleval); // } // } // } //} //draw time line with moving cursor void timeline() { strokeWeight(2); stroke(240); rect((cornarval[3][0]+xoffset)/2, cornarval[3][1]+yoffset+10, cornarval[3][0]+xoffset, 1); strokeWeight(1); stroke(57); fill(0,150,255); rect(timepos, cornarval[3][1]+yoffset+10, 10,10); if (mouseontime = overRect(timepos,cornarval[3][1]+yoffset+10,25,25)) { fill(200,255,0); rect(timepos, cornarval[3][1]+yoffset+10, 10,10); if(mousePressed == true) val=0; } fill(0); text("Time = ",timepos, cornarval[3][1]+yoffset+10+20); text(index*5,timepos+40, cornarval[3][1]+yoffset+10+20); if (overRect((cornarval[3][0])/20, cornarval[3][1]+yoffset+5, (cornarval[3][0]+xoffset)-20, 10)) { noFill(); if (mouseX*4 < totallen) { rect(mouseX, cornarval[3][1]+yoffset+10, 10,10); text("Time = ",mouseX, cornarval[3][1]+yoffset+10+20); text(mouseX*5*4,mouseX+40, cornarval[3][1]+yoffset+10+20); if (mousePressed) index = mouseX*4; } } } //left click to increase framerate, right click to decreas void fratechange() { fill(30); text("Left Click +, Right Click -", cornarval[3][0]+xoffset+30, cornarval[3][1]+yoffset); stroke(255); fill(78); rect(cornarval[3][0]+xoffset+40, cornarval[3][1]+yoffset+20,20,20); if (mouseonframe = overRect(cornarval[3][0]+xoffset+40,cornarval[3][1]+yoffset+20,20,20)) { fill(146); rect(cornarval[3][0]+xoffset+40, cornarval[3][1]+yoffset+20,20,20); if (mousePressed && (mouseButton == LEFT)) { if (frate > 100) { }else { frate = frate + 1; } } else if (mousePressed && (mouseButton == RIGHT)) { if (frate <2) { }else { frate = frate - 1; } } } fill(255); text(frate*5,cornarval[3][0]+xoffset+35, cornarval[3][1]+yoffset+22); fill(0); text("Framerate",cornarval[3][0]+xoffset+55, cornarval[3][1]+yoffset+20); } //resume from pause void mouseReleased() { if (mouseontime) val=1; } void playername() { int counter = 0; fill(33); text("[Team Putney Rangers]",cornarval[3][0]+xoffset+30, yoffset-20); for (int i = 0; i < gps2jersey.length/2-1; i++) { if (playerPos[i][0][1] != -100) { fill(237,0,0); rect(cornarval[3][0]+xoffset+40, yoffset+20*counter,15,15); fill(255); text(gps2jersey[i][0],cornarval[3][0]+xoffset+35, yoffset+20*counter+3); fill(0); text(gps2jersey[i][1],cornarval[3][0]+xoffset+53, yoffset+20*counter+3); counter++; } } fill(33); text("[Team Pennant Hills]",cornarval[3][0]+xoffset+30, 50+yoffset+20*counter-20); for (int i = gps2jersey.length/2; i < gps2jersey.length-1; i++) { if (playerPos[i][0][1] != -100) { fill(10,255,5); rect(cornarval[3][0]+xoffset+40, 50+yoffset+20*counter,15,15); fill(33); text(gps2jersey[i][0],cornarval[3][0]+xoffset+35, 50+yoffset+20*counter+3); fill(0); text(gps2jersey[i][1],cornarval[3][0]+xoffset+53, 50+yoffset+20*counter+3); counter++; } } } //drag across the time like to change time frame void mouseDragged() { if (mouseontime) index = mouseX*4; } //determine on and off of the player display void mousePressed() { //play and pause button if(mouseonplay) { if (playonoff == false) { playcolor = 255; val = 1; } else if (playonoff == true) { playcolor = 0; val = 0; } playonoff = !playonoff; } if(mouseonRestart) index = 0; } //check the position of mouse is on the button or not boolean overRect(float x, float y, float width, float height) { if (mouseX >= x-width/2 && mouseX <= x+width && mouseY >= y-height/2 && mouseY <= y+height) { return true; } else { return false; } } boolean overCircle(float x, float y, int diameter, float px, float py) { float disX = x - px; float disY = y - py; if(sqrt(sq(disX) + sq(disY)) < diameter/2 ) { return true; } else { return false; } }