Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #########
- # ZONES #
- #########
- # The zones in the below algorithms are as follows:
- # Stage 1 and 2 (and 3 for the rectangular zones) where "5" is the strike zone:
- #############
- # 1 # 2 # 3 #
- #############
- # 4 # 5 # 6 #
- #############
- # 7 # 8 # 9 #
- #############
- # Stage 3 for the rule book strike zone, where "17" is directly behind the strike zone:
- ##########################
- # 10 # 11 # 12 # 13 # 14 #
- ##########################
- # 15 # 16 # 17 # 18 # 19 #
- ##########################
- # 20 # 21 # 22 # 23 # 24 #
- ##########################
- # In Stage 3, the areas above, below, and in the triangular part of the strike zone take 12, 17, and 22 and map them to 25, 26, and
- # 27, respectively.
- ############################
- # 3D Rule Book Strike Zone #
- ############################
- dist_3D_to_SZ <- function(Pfx){
- # This function finds the minimum distance from the pitch to the strike zone in three dimensions
- # Pfx is a list containing ax, ay, az, vx0, vy0, vz0, x0, y0, z0, sz_top, and sz_bot
- # Set various locations in x, y, and z
- sz_front_y <- 17/12;
- sz_middle_y <- 17/24;
- sz_back_y <- 0;
- mitt_y <- -55/24;
- ground_z <- 0.125;
- sz_left_x <- -17/24;
- sz_right_x <- 17/24;
- sz_top_z <- Pfx$sz_top;
- sz_bottom_z <- Pfx$sz_bot;
- sz_middle_x <- (sz_left_x + sz_right_x)/2;
- sz_middle_z <- (sz_top_z + sz_bottom_z)/2;
- ball_radius <- 0.125;
- # Find the time to various distances in y
- # STAGE 1: Time to the front of home plate
- t_to_front <- (-Pfx$vy0 - sqrt(Pfx$vy0^2 - 2*Pfx$ay*(Pfx$y0 - sz_front_y)))/Pfx$ay;
- # STAGE 2: Time to the midpoint of home plate
- t_to_middle <- (-Pfx$vy0 - sqrt(Pfx$vy0^2 - 2*Pfx$ay*(Pfx$y0 - sz_middle_y)))/Pfx$ay;
- # STAGE 3: Time to the back of home plate
- t_to_back <- (-Pfx$vy0 - sqrt(Pfx$vy0^2 - 2*Pfx$ay*(Pfx$y0 - sz_back_y)))/Pfx$ay;
- # Time to catcher's mitt
- t_to_mitt <- (-Pfx$vy0 - sqrt(Pfx$vy0^2 - 2*Pfx$ay*(Pfx$y0 - mitt_y)))/Pfx$ay;
- # Time to ball hitting ground
- disc_z <- Pfx$vz0^2 - 2*Pfx$az*(Pfx$z0 - ground_z);
- if (disc_z > 0){
- t_to_ground <- (-Pfx$vz0 - sqrt(disc_z))/Pfx$az;
- } else {
- t_to_ground <- t_to_mitt + 1;
- }
- # Find the location at the front of the strike zone
- px <- x_eval(Pfx,t_to_front);
- pz <- z_eval(Pfx,t_to_front);
- pvx <- vx_eval(Pfx,t_to_front);
- pvz <- vz_eval(Pfx,t_to_front);
- # Find the number of stages before the ball hits the ground OR the catcher's mitt
- if(t_to_ground > t_to_middle){
- STAGES <- 3;
- } else if (t_to_ground > t_to_front){
- STAGES <- 2;
- } else {
- STAGES <- 1;
- }
- # Allocate space for times when the pitch switches zones
- ZONE_TIMES_12 <- array(0,dim=8);
- ZONE_TIMES_3 <- array(0,dim=12);
- # Left Vertical
- disc_LV <- Pfx$vx0^2 - 2*Pfx$ax*(Pfx$x0 - sz_left_x);
- if (disc_LV > 0 && Pfx$ax != 0) {
- ZONE_TIMES_12[1] <- (-Pfx$vx0 + sqrt(disc_LV))/Pfx$ax;
- ZONE_TIMES_12[2] <- (-Pfx$vx0 - sqrt(disc_LV))/Pfx$ax;
- } else if (Pfx$ax == 0) {
- ZONE_TIMES_12[1] <- -(Pfx$x0-sz_left_x)/Pfx$vx0;
- }
- # Right Vertical
- disc_RV <- Pfx$vx0^2 - 2*Pfx$ax*(Pfx$x0 - sz_right_x);
- if (disc_RV > 0 && Pfx$ax != 0) {
- ZONE_TIMES_12[3] <- (-Pfx$vx0 + sqrt(disc_RV))/Pfx$ax;
- ZONE_TIMES_12[4] <- (-Pfx$vx0 - sqrt(disc_RV))/Pfx$ax;
- } else if (Pfx$ax == 0) {
- ZONE_TIMES_12[3] <- -(Pfx$x0-sz_right_x)/Pfx$vx0;
- }
- # Top Horizontal
- disc_TH <- Pfx$vz0^2 - 2*Pfx$az*(Pfx$z0 - sz_top_z);
- if (disc_TH > 0 && Pfx$az != 0) {
- ZONE_TIMES_12[5] <- (-Pfx$vz0 + sqrt(disc_TH))/Pfx$az;
- ZONE_TIMES_12[6] <- (-Pfx$vz0 - sqrt(disc_TH))/Pfx$az;
- ZONE_TIMES_3[9] <- ZONE_TIMES_12[5];
- ZONE_TIMES_3[10] <- ZONE_TIMES_12[6];
- } else if (Pfx$az == 0) {
- ZONE_TIMES_12[5] <- -(Pfx$z0-sz_top_z)/Pfx$vz0;
- ZONE_TIMES_3[9] <- ZONE_TIMES_12[5];
- }
- # Bottom Horizontal
- disc_BH <- Pfx$vz0^2 - 2*Pfx$az*(Pfx$z0 - sz_bottom_z);
- if (disc_BH > 0 && Pfx$az != 0) {
- ZONE_TIMES_12[7] <- (-Pfx$vz0 + sqrt(disc_BH))/Pfx$az;
- ZONE_TIMES_12[8] <- (-Pfx$vz0 - sqrt(disc_BH))/Pfx$az;
- ZONE_TIMES_3[11] <- ZONE_TIMES_12[7];
- ZONE_TIMES_3[12] <- ZONE_TIMES_12[8];
- } else if (Pfx$az == 0) {
- ZONE_TIMES_12[7] <- -(Pfx$z0-sz_bottom_z)/Pfx$vz0;
- }
- # Left End
- a <- 0.5*(Pfx$ax - Pfx$ay);
- b <- Pfx$vx0 - Pfx$vy0;
- c <- Pfx$x0 + (17/12) - Pfx$y0;
- disc_LE <- b^2 - 4*a*c;
- if (disc_LE > 0){
- ZONE_TIMES_3[1] <- (-b + sqrt(disc_LE))/(2*a);
- ZONE_TIMES_3[2] <- (-b - sqrt(disc_LE))/(2*a);
- }
- # Left Middle
- a <- 0.5*(Pfx$ax - Pfx$ay);
- b <- Pfx$vx0 - Pfx$vy0;
- c <- Pfx$x0 - Pfx$y0;
- disc_LM <- b^2 - 4*a*c;
- if (disc_LM > 0){
- ZONE_TIMES_3[3] <- (-b + sqrt(disc_LM))/(2*a);
- ZONE_TIMES_3[4] <- (-b - sqrt(disc_LM))/(2*a);
- }
- # Right Middle
- a <- 0.5*(Pfx$ax + Pfx$ay);
- b <- Pfx$vx0 + Pfx$vy0;
- c <- Pfx$x0 + Pfx$y0;
- disc_RM <- b^2 - 4*a*c;
- if (disc_LM > 0){
- ZONE_TIMES_3[5] <- (-b + sqrt(disc_RM))/(2*a);
- ZONE_TIMES_3[6] <- (-b - sqrt(disc_RM))/(2*a);
- }
- # Right End
- a <- 0.5*(Pfx$ax + Pfx$ay);
- b <- Pfx$vx0 + Pfx$vy0;
- c <- Pfx$x0 - (17/12) + Pfx$y0;
- disc_RE <- b^2 - 4*a*c;
- if (disc_RE > 0){
- ZONE_TIMES_3[7] <- (-b + sqrt(disc_RE))/(2*a);
- ZONE_TIMES_3[8] <- (-b - sqrt(disc_RE))/(2*a);
- }
- # Allocate an array for moves between the zones
- ZONE_MOVE_1 <- array(0,dim=8);
- ZONE_MOVE_2 <- array(0,dim=8);
- ZONE_MOVE_3 <- array(0,dim=12);
- ZONE_TIMES_1 <- array(0,dim=8);
- ZONE_TIMES_2 <- array(0,dim=8);
- # Check for times within range of 50 feet to the middle of the strike zone
- for(i in 1:8){
- if(ZONE_TIMES_12[i] > 0 && ZONE_TIMES_12[i] < t_to_front) {
- ZONE_MOVE_1[i] <- 1;
- ZONE_TIMES_1[i] <- ZONE_TIMES_12[i];
- }
- if(ZONE_TIMES_12[i] > t_to_front && ZONE_TIMES_12[i] < t_to_middle) {
- ZONE_MOVE_2[i] <- 1;
- ZONE_TIMES_2[i] <- ZONE_TIMES_12[i];
- }
- }
- for(i in 1:12){
- if(ZONE_TIMES_3[i] > t_to_middle && ZONE_TIMES_3[i] < t_to_mitt) {
- ZONE_MOVE_3[i] <- 1;
- }
- }
- # Sort the times for zone switches and their indices
- ZONE_TIMES_1_SORT <- sort(ZONE_TIMES_1,decreasing=FALSE,index.return=TRUE);
- ZONE_TIMES_2_SORT <- sort(ZONE_TIMES_2,decreasing=FALSE,index.return=TRUE);
- ZONE_TIMES_3_SORT <- sort(ZONE_TIMES_3,decreasing=FALSE,index.return=TRUE);
- MOVES_1 <- sum(ZONE_MOVE_1);
- MOVES_2 <- sum(ZONE_MOVE_2);
- MOVES_3 <- sum(ZONE_MOVE_3);
- ZONES_1 <- array(0,dim=(MOVES_1+1));
- ZONES_2 <- array(0,dim=(MOVES_2+1));
- ZONES_3 <- array(0,dim=(MOVES_3+1));
- ZONES_TRI <- array(0,dim=(MOVES_3+1));
- SWITCH_1 <- array(0,dim=(MOVES_1+2));
- SWITCH_2 <- array(0,dim=(MOVES_2+2));
- SWITCH_3 <- array(0,dim=(MOVES_3+2));
- # Find the zone in which the pitch starts
- ZONES_1[1] <- zone_check(Pfx,sz_left_x,sz_right_x,sz_top_z,sz_bottom_z);
- SWITCH_1[1] <- 0;
- k <- 1;
- for(i in ZONE_TIMES_1_SORT$ix){
- if(ZONE_MOVE_1[i] == 1){
- k <- k+1;
- if(i <= 4){
- vx <- vx_eval(Pfx,ZONE_TIMES_1[i]);
- if(vx > 0){
- ZONES_1[k] <- ZONES_1[k-1] + 1;
- } else {
- ZONES_1[k] <- ZONES_1[k-1] - 1;
- }
- } else {
- vz <- vz_eval(Pfx,ZONE_TIMES_1[i]);
- if(vz > 0){
- ZONES_1[k] <- ZONES_1[k-1] - 3;
- } else {
- ZONES_1[k] <- ZONES_1[k-1] + 3;
- }
- }
- SWITCH_1[k] <- ZONE_TIMES_1[i];
- }
- }
- SWITCH_1[MOVES_1+2] <- t_to_front;
- ZONES_2[1] <- ZONES_1[MOVES_1+1];
- SWITCH_2[1] <- t_to_front;
- k <- 1;
- for(i in ZONE_TIMES_2_SORT$ix){
- if(ZONE_MOVE_2[i] == 1){
- k <- k+1;
- if(i <= 4){
- vx <- vx_eval(Pfx,ZONE_TIMES_2[i]);
- if(vx > 0){
- ZONES_2[k] <- ZONES_2[k-1] + 1;
- } else {
- ZONES_2[k] <- ZONES_2[k-1] - 1;
- }
- } else {
- vz <- vz_eval(Pfx,ZONE_TIMES_2[i]);
- if(vz > 0){
- ZONES_2[k] <- ZONES_2[k-1] - 3;
- } else {
- ZONES_2[k] <- ZONES_2[k-1] + 3;
- }
- }
- SWITCH_2[k] <- ZONE_TIMES_2[i];
- }
- }
- SWITCH_2[MOVES_2+2] <- t_to_middle;
- # Re-map the zones from the front end of the strike zone to the back end
- ZONE_TEMP <- ZONES_2[MOVES_2+1];
- if (ZONE_TEMP == 1){
- ZONES_3[1] <- 10;
- } else if (ZONE_TEMP == 2){
- ZONES_3[1] <- 12;
- } else if (ZONE_TEMP == 3){
- ZONES_3[1] <- 14;
- } else if (ZONE_TEMP == 4){
- ZONES_3[1] <- 15;
- } else if (ZONE_TEMP == 5){
- ZONES_3[1] <- 17;
- } else if (ZONE_TEMP == 6){
- ZONES_3[1] <- 19;
- } else if (ZONE_TEMP == 7){
- ZONES_3[1] <- 20;
- } else if (ZONE_TEMP == 8){
- ZONES_3[1] <- 22;
- } else if (ZONE_TEMP == 9){
- ZONES_3[1] <- 24;
- }
- ZONES_TRI[1] <- 1;
- SWITCH_3[1] <- t_to_middle;
- k <- 1;
- for(i in ZONE_TIMES_3_SORT$ix){
- if(ZONE_MOVE_3[i] == 1){
- k <- k+1;
- if (ZONE_TIMES_3[i] < t_to_back && ZONE_TIMES_3[i] > t_to_middle) {
- ZONES_TRI[k] <- 1;
- }
- if (i <= 4){
- vx <- vx_eval(Pfx,ZONE_TIMES_3[i]);
- vy <- vy_eval(Pfx,ZONE_TIMES_3[i]);
- if (abs(vx) > abs(vy) && vx < 0) {
- ZONES_3[k] <- ZONES_3[k-1] - 1;
- } else {
- ZONES_3[k] <- ZONES_3[k-1] + 1;
- }
- } else if (i <= 8) {
- vx <- vx_eval(Pfx,ZONE_TIMES_3[i]);
- vy <- vy_eval(Pfx,ZONE_TIMES_3[i]);
- if (abs(vx) > abs(vy) && vx > 0) {
- ZONES_3[k] <- ZONES_3[k-1] + 1;
- } else {
- ZONES_3[k] <- ZONES_3[k-1] - 1;
- }
- } else {
- vz <- vz_eval(Pfx,ZONE_TIMES_3[i]);
- if (vz > 0){
- ZONES_3[k] <- ZONES_3[k-1] - 5;
- } else {
- ZONES_3[k] <- ZONES_3[k-1] + 5;
- }
- }
- SWITCH_3[k] <- ZONE_TIMES_3[i];
- }
- }
- SWITCH_3[MOVES_3+2] <- t_to_mitt;
- MOVE_CTR <- 1;
- dist_sz <- 55;
- # Find the distances over STAGE 1
- while(MOVE_CTR <= (MOVES_1+1) && SWITCH_1[MOVE_CTR] < t_to_ground){
- t_0 <- SWITCH_1[MOVE_CTR];
- t_1 <- min(SWITCH_1[MOVE_CTR+1],t_to_ground);
- if(ZONES_1[MOVE_CTR] == 1){
- dist_sz_temp <- min_corner(Pfx,sz_left_x,sz_front_y,sz_top_z,t_0,t_1);
- } else if(ZONES_1[MOVE_CTR] == 2){
- dist_sz_temp <- min_edge_yz(Pfx,sz_front_y,sz_top_z,t_0,t_1);
- } else if(ZONES_1[MOVE_CTR] == 3){
- dist_sz_temp <- min_corner(Pfx,sz_right_x,sz_front_y,sz_top_z,t_0,t_1);
- } else if(ZONES_1[MOVE_CTR] == 4){
- dist_sz_temp <- min_edge_xy(Pfx,sz_left_x,sz_front_y,t_0,t_1);
- } else if(ZONES_1[MOVE_CTR] == 5){
- dist_sz_temp <- min_face_y(Pfx,sz_front_y,t_0,t_1);
- } else if(ZONES_1[MOVE_CTR] == 6){
- dist_sz_temp <- min_edge_xy(Pfx,sz_right_x,sz_front_y,t_0,t_1);
- } else if(ZONES_1[MOVE_CTR] == 7){
- dist_sz_temp <- min_corner(Pfx,sz_left_x,sz_front_y,sz_bottom_z,t_0,t_1);
- } else if(ZONES_1[MOVE_CTR] == 8){
- dist_sz_temp <- min_edge_yz(Pfx,sz_front_y,sz_bottom_z,t_0,t_1);
- } else if(ZONES_1[MOVE_CTR] == 9){
- dist_sz_temp <- min_corner(Pfx,sz_right_x,sz_front_y,sz_bottom_z,t_0,t_1);
- }
- MOVE_CTR <- MOVE_CTR + 1;
- if (dist_sz_temp < dist_sz){
- dist_sz <- dist_sz_temp;
- stage <- 1;
- zone <- ZONES_1[MOVE_CTR-1];
- }
- if (dist_sz < ball_radius){
- OUT <- list(dist_sz = max(dist_sz-ball_radius,0), stage = stage, zone = zone, px = px, pz = pz, pvx = pvx, pvz = pvz);
- return(OUT);
- }
- }
- # Find the distances over STAGE 2
- if (STAGES > 1){
- MOVE_CTR <- 1;
- while(MOVE_CTR <= (MOVES_2+1) && SWITCH_2[MOVE_CTR] < t_to_ground){
- t_1 <- SWITCH_2[MOVE_CTR];
- t_2 <- min(SWITCH_2[MOVE_CTR+1],t_to_ground);
- if(ZONES_2[MOVE_CTR] == 1){
- dist_sz_temp <- min_edge_xz(Pfx,sz_left_x,sz_top_z,t_1,t_2);
- } else if(ZONES_2[MOVE_CTR] == 2){
- dist_sz_temp <- min_face_z(Pfx,sz_top_z,t_1,t_2);
- } else if(ZONES_2[MOVE_CTR] == 3){
- dist_sz_temp <- min_edge_xz(Pfx,sz_right_x,sz_top_z,t_1,t_2);
- } else if(ZONES_2[MOVE_CTR] == 4){
- dist_sz_temp <- min_face_x(Pfx,sz_left_x,t_1,t_2);
- } else if(ZONES_2[MOVE_CTR] == 5){
- dist_sz_temp <- 0;
- } else if(ZONES_2[MOVE_CTR] == 6){
- dist_sz_temp <- min_face_x(Pfx,sz_right_x,t_1,t_2);
- } else if(ZONES_2[MOVE_CTR] == 7){
- dist_sz_temp <- min_edge_xz(Pfx,sz_left_x,sz_bottom_z,t_1,t_2);
- } else if(ZONES_2[MOVE_CTR] == 8){
- dist_sz_temp <- min_face_z(Pfx,sz_bottom_z,t_1,t_2);
- } else if(ZONES_2[MOVE_CTR] == 9){
- dist_sz_temp <- min_edge_xz(Pfx,sz_right_x,sz_bottom_z,t_1,t_2);
- }
- MOVE_CTR <- MOVE_CTR + 1;
- if (dist_sz_temp < dist_sz){
- dist_sz <- dist_sz_temp;
- stage <- 2;
- zone <- ZONES_2[MOVE_CTR-1];
- }
- if (dist_sz < ball_radius){
- OUT <- list(dist_sz = max(dist_sz-ball_radius,0), stage = stage, zone = zone, px = px, pz = pz, pvx = pvx, pvz = pvz);
- return(OUT);
- }
- }
- }
- tri_flag <- 0;
- # Find the distances over STAGE 3
- if (STAGES > 2){
- MOVE_CTR <- 1;
- while (MOVE_CTR <= (MOVES_3+1) && SWITCH_3[MOVE_CTR] < t_to_ground){
- t_2 <- SWITCH_3[MOVE_CTR];
- t_3 <- min(SWITCH_3[MOVE_CTR+1],t_to_ground);
- if(ZONES_3[MOVE_CTR] == 10){
- dist_sz_temp <- min_corner(Pfx,sz_left_x,sz_middle_y,sz_top_z,t_2,t_3);
- } else if (ZONES_3[MOVE_CTR] == 11) {
- dist_sz_temp <- min_diag_edge_xy(Pfx,sz_left_x,sz_middle_y,sz_top_z,sz_middle_x,sz_back_y,t_2,t_3);
- } else if (ZONES_3[MOVE_CTR] == 12) {
- if (ZONES_TRI[MOVE_CTR] == 1) {
- dist_sz_temp <- min_face_z(Pfx,sz_top_z,t_2,t_3);
- tri_flag <- 1;
- } else {
- dist_sz_temp <- min_corner(Pfx,sz_middle_x,sz_back_y,sz_top_z,t_2,t_3);
- }
- } else if (ZONES_3[MOVE_CTR] == 13) {
- dist_sz_temp <- min_diag_edge_xy(Pfx,sz_right_x,sz_middle_y,sz_top_z,sz_middle_x,sz_back_y,t_2,t_3);
- } else if (ZONES_3[MOVE_CTR] == 14) {
- dist_sz_temp <- min_corner(Pfx,sz_right_x,sz_middle_y,sz_top_z,t_2,t_3);
- } else if (ZONES_3[MOVE_CTR] == 15) {
- dist_sz_temp <- min_edge_xy(Pfx,sz_left_x,sz_middle_y,t_2,t_3);
- } else if (ZONES_3[MOVE_CTR] == 16) {
- dist_sz_temp <- min_diag_face_xy(Pfx,1,1,0,sz_middle_x,sz_back_y,sz_bottom_z,t_2,t_3);
- } else if (ZONES_3[MOVE_CTR] == 17) {
- if (ZONES_TRI[MOVE_CTR] == 1){
- dist_sz_temp <- 0;
- tri_flag <- 1;
- } else {
- dist_sz_temp <- min_edge_xy(Pfx,sz_middle_x,sz_back_y,t_2,t_3);
- }
- } else if (ZONES_3[MOVE_CTR] == 18) {
- dist_sz_temp <- min_diag_face_xy(Pfx,-1,1,0,sz_middle_x,sz_back_y,sz_bottom_z,t_2,t_3);
- } else if (ZONES_3[MOVE_CTR] == 19) {
- dist_sz_temp <- min_edge_xy(Pfx,sz_right_x,sz_middle_y,t_2,t_3);
- } else if (ZONES_3[MOVE_CTR] == 20) {
- dist_sz_temp <- min_corner(Pfx,sz_left_x,sz_middle_y,sz_bottom_z,t_2,t_3);
- } else if (ZONES_3[MOVE_CTR] == 21) {
- dist_sz_temp <- min_diag_edge_xy(Pfx,sz_left_x,sz_middle_y,sz_bottom_z,sz_middle_x,sz_back_y,t_2,t_3);
- } else if (ZONES_3[MOVE_CTR] == 22) {
- if (ZONES_TRI[MOVE_CTR] == 1) {
- dist_sz_temp <- min_face_z(Pfx,sz_bottom_z,t_2,t_3);
- tri_flag <- 1;
- } else {
- dist_sz_temp <- min_corner(Pfx,sz_middle_x,sz_back_y,sz_bottom_z,t_2,t_3);
- }
- } else if (ZONES_3[MOVE_CTR] == 23) {
- dist_sz_temp <- min_diag_edge_xy(Pfx,sz_right_x,sz_middle_y,sz_bottom_z,sz_middle_x,sz_back_y,t_2,t_3);
- } else if (ZONES_3[MOVE_CTR] == 24) {
- dist_sz_temp <- min_corner(Pfx,sz_right_x,sz_middle_y,sz_bottom_z,t_2,t_3);
- }
- MOVE_CTR <- MOVE_CTR + 1;
- if (dist_sz_temp < dist_sz){
- dist_sz <- dist_sz_temp;
- stage <- 3;
- zone <- ZONES_3[MOVE_CTR-1];
- if (tri_flag == 1){
- if (zone == 12) {
- zone <- 25;
- } else if (zone == 17) {
- zone <- 26;
- } else {
- zone <- 27;
- }
- tri_flag <- 0;
- }
- }
- if (dist_sz < ball_radius){
- OUT <- list(dist_sz = max(dist_sz-ball_radius,0), stage = stage, zone = zone, px = px, pz = pz, pvx = pvx, pvz = pvz);
- return(OUT);
- }
- }
- }
- OUT <- list(dist_sz = max(dist_sz-ball_radius,0), stage = stage, zone = zone, px = px, pz = pz, pvx = pvx, pvz = pvz);
- return(OUT);
- }
- ########################
- # 3D Strike Zone (Box) #
- ########################
- dist_3D_to_SZ_box <- function(Pfx){
- # This function finds the minimum distance from the pitch to a strike zone box in three dimensions
- # Pfx is a list containing ax, ay, az, vx0, vy0, vz0, x0, y0, z0, sz_top, and sz_bot
- # Set various locations in x, y, and z
- sz_front_y <- 17/12;
- sz_back_y <- 17/24;
- plate_front <- 17/12;
- mitt_y <- -55/24;
- ground_z <- 0.125;
- sz_left_x <- -17/24;
- sz_right_x <- 17/24;
- sz_top_z <- Pfx$sz_top;
- sz_bottom_z <- Pfx$sz_bot;
- ball_radius <- 0.125;
- # Find the time to various distances in y
- # STAGE 1: Time to the front of home plate
- t_to_front <- (-Pfx$vy0 - sqrt(Pfx$vy0^2 - 2*Pfx$ay*(Pfx$y0 - sz_front_y)))/Pfx$ay;
- # Time to the front of home plate
- t_to_plate <- (-Pfx$vy0 - sqrt(Pfx$vy0^2 - 2*Pfx$ay*(Pfx$y0 - plate_front)))/Pfx$ay;
- # STAGE 2: Time to the back of home plate
- t_to_back <- (-Pfx$vy0 - sqrt(Pfx$vy0^2 - 2*Pfx$ay*(Pfx$y0 - sz_back_y)))/Pfx$ay;
- # Stage 3: Time to catcher's mitt
- t_to_mitt <- (-Pfx$vy0 - sqrt(Pfx$vy0^2 - 2*Pfx$ay*(Pfx$y0 - mitt_y)))/Pfx$ay;
- # Time to ball hitting ground
- disc_z <- Pfx$vz0^2 - 2*Pfx$az*(Pfx$z0 - ground_z);
- if (disc_z > 0){
- t_to_ground <- (-Pfx$vz0 - sqrt(disc_z))/Pfx$az;
- } else {
- t_to_ground <- t_to_mitt + 1;
- }
- # Find the location at the front of the strike zone
- px <- x_eval(Pfx,t_to_plate);
- pz <- z_eval(Pfx,t_to_plate);
- # Find the number of stages before the ball hits the ground OR the catcher's mitt
- if(t_to_ground > t_to_back){
- STAGES <- 3;
- } else if (t_to_ground > t_to_front){
- STAGES <- 2;
- } else {
- STAGES <- 1;
- }
- # Allocate space for times when the pitch switches zones
- ZONE_TIMES <- array(0,dim=8);
- # Left Vertical
- disc_LV <- Pfx$vx0^2 - 2*Pfx$ax*(Pfx$x0 - sz_left_x);
- if (disc_LV > 0 && Pfx$ax != 0) {
- ZONE_TIMES[1] <- (-Pfx$vx0 + sqrt(disc_LV))/Pfx$ax;
- ZONE_TIMES[2] <- (-Pfx$vx0 - sqrt(disc_LV))/Pfx$ax;
- } else if (Pfx$ax == 0) {
- ZONE_TIMES[1] <- -(Pfx$x0-sz_left_x)/Pfx$vx0;
- }
- # Right Vertical
- disc_RV <- Pfx$vx0^2 - 2*Pfx$ax*(Pfx$x0 - sz_right_x);
- if (disc_RV > 0 && Pfx$ax != 0) {
- ZONE_TIMES[3] <- (-Pfx$vx0 + sqrt(disc_RV))/Pfx$ax;
- ZONE_TIMES[4] <- (-Pfx$vx0 - sqrt(disc_RV))/Pfx$ax;
- } else if (Pfx$ax == 0) {
- ZONE_TIMES[3] <- -(Pfx$x0-sz_right_x)/Pfx$vx0;
- }
- # Top Horizontal
- disc_TH <- Pfx$vz0^2 - 2*Pfx$az*(Pfx$z0 - sz_top_z);
- if (disc_TH > 0 && Pfx$az != 0) {
- ZONE_TIMES[5] <- (-Pfx$vz0 + sqrt(disc_TH))/Pfx$az;
- ZONE_TIMES[6] <- (-Pfx$vz0 - sqrt(disc_TH))/Pfx$az;
- } else if (Pfx$az == 0) {
- ZONE_TIMES[5] <- -(Pfx$z0-sz_top_z)/Pfx$vz0;
- }
- # Bottom Horizontal
- disc_BH <- Pfx$vz0^2 - 2*Pfx$az*(Pfx$z0 - sz_bottom_z);
- if (disc_BH > 0 && Pfx$az != 0) {
- ZONE_TIMES[7] <- (-Pfx$vz0 + sqrt(disc_BH))/Pfx$az;
- ZONE_TIMES[8] <- (-Pfx$vz0 - sqrt(disc_BH))/Pfx$az;
- } else if (Pfx$az == 0) {
- ZONE_TIMES[7] <- -(Pfx$z0-sz_bottom_z)/Pfx$vz0;
- }
- # Allocate an array for moves between the zones
- ZONE_MOVE_1 <- array(0,dim=8);
- ZONE_MOVE_2 <- array(0,dim=8);
- ZONE_MOVE_3 <- array(0,dim=8);
- ZONE_TIMES_1 <- array(0,dim=8);
- ZONE_TIMES_2 <- array(0,dim=8);
- ZONE_TIMES_3 <- array(0,dim=8);
- # Check for times within range of 50 feet to the middle of the strike zone
- for(i in 1:8){
- if(ZONE_TIMES[i] > 0 && ZONE_TIMES[i] < t_to_front) {
- ZONE_MOVE_1[i] <- 1;
- ZONE_TIMES_1[i] <- ZONE_TIMES[i];
- }
- if(ZONE_TIMES[i] > t_to_front && ZONE_TIMES[i] < t_to_back) {
- ZONE_MOVE_2[i] <- 1;
- ZONE_TIMES_2[i] <- ZONE_TIMES[i];
- }
- if(ZONE_TIMES[i] > t_to_back && ZONE_TIMES[i] < t_to_mitt) {
- ZONE_MOVE_3[i] <- 1;
- ZONE_TIMES_3[i] <- ZONE_TIMES[i];
- }
- }
- # Sort the times for zone switches and their indices
- ZONE_TIMES_1_SORT <- sort(ZONE_TIMES_1,decreasing=FALSE,index.return=TRUE);
- ZONE_TIMES_2_SORT <- sort(ZONE_TIMES_2,decreasing=FALSE,index.return=TRUE);
- ZONE_TIMES_3_SORT <- sort(ZONE_TIMES_3,decreasing=FALSE,index.return=TRUE);
- MOVES_1 <- sum(ZONE_MOVE_1);
- MOVES_2 <- sum(ZONE_MOVE_2);
- MOVES_3 <- sum(ZONE_MOVE_3);
- ZONES_1 <- array(0,dim=(MOVES_1+1));
- ZONES_2 <- array(0,dim=(MOVES_2+1));
- ZONES_3 <- array(0,dim=(MOVES_3+1));
- SWITCH_1 <- array(0,dim=(MOVES_1+2));
- SWITCH_2 <- array(0,dim=(MOVES_2+2));
- SWITCH_3 <- array(0,dim=(MOVES_3+2));
- # Find the zone in which the pitch starts
- ZONES_1[1] <- zone_check(Pfx,sz_left_x,sz_right_x,sz_top_z,sz_bottom_z);
- SWITCH_1[1] <- 0;
- k <- 1;
- for(i in ZONE_TIMES_1_SORT$ix){
- if(ZONE_MOVE_1[i] == 1){
- k <- k+1;
- if(i <= 4){
- vx <- vx_eval(Pfx,ZONE_TIMES_1[i]);
- if(vx > 0){
- ZONES_1[k] <- ZONES_1[k-1] + 1;
- } else {
- ZONES_1[k] <- ZONES_1[k-1] - 1;
- }
- } else {
- vz <- vz_eval(Pfx,ZONE_TIMES_1[i]);
- if(vz > 0){
- ZONES_1[k] <- ZONES_1[k-1] - 3;
- } else {
- ZONES_1[k] <- ZONES_1[k-1] + 3;
- }
- }
- SWITCH_1[k] <- ZONE_TIMES_1[i];
- }
- }
- SWITCH_1[MOVES_1+2] <- t_to_front;
- ZONES_2[1] <- ZONES_1[MOVES_1+1];
- SWITCH_2[1] <- t_to_front;
- k <- 1;
- for(i in ZONE_TIMES_2_SORT$ix){
- if(ZONE_MOVE_2[i] == 1){
- k <- k+1;
- if(i <= 4){
- vx <- vx_eval(Pfx,ZONE_TIMES_2[i]);
- if(vx > 0){
- ZONES_2[k] <- ZONES_2[k-1] + 1;
- } else {
- ZONES_2[k] <- ZONES_2[k-1] - 1;
- }
- } else {
- vz <- vz_eval(Pfx,ZONE_TIMES_1[i]);
- if(vz > 0){
- ZONES_2[k] <- ZONES_2[k-1] - 3;
- } else {
- ZONES_2[k] <- ZONES_2[k-1] + 3;
- }
- }
- SWITCH_2[k] <- ZONE_TIMES_2[i];
- }
- }
- SWITCH_2[MOVES_2+2] <- t_to_back;
- ZONES_3[1] <- ZONES_2[MOVES_2+1];
- SWITCH_3[1] <- t_to_back;
- k <- 1;
- for(i in ZONE_TIMES_3_SORT$ix){
- if(ZONE_MOVE_3[i] == 1){
- k <- k+1;
- if(i <= 4){
- vx <- vx_eval(Pfx,ZONE_TIMES_3[i]);
- if(vx > 0){
- ZONES_3[k] <- ZONES_3[k-1] + 1;
- } else {
- ZONES_3[k] <- ZONES_3[k-1] - 1;
- }
- } else {
- vz <- vz_eval(Pfx,ZONE_TIMES_3[i]);
- if(vz > 0){
- ZONES_3[k] <- ZONES_3[k-1] - 3;
- } else {
- ZONES_3[k] <- ZONES_3[k-1] + 3;
- }
- }
- SWITCH_3[k] <- ZONE_TIMES_3[i];
- }
- }
- SWITCH_3[MOVES_3+2] <- t_to_mitt;
- MOVE_CTR <- 1;
- dist_sz <- 55;
- # Find the distances over STAGE 1
- while(MOVE_CTR <= (MOVES_1+1) && SWITCH_1[MOVE_CTR] < t_to_ground){
- t_0 <- SWITCH_1[MOVE_CTR];
- t_1 <- min(SWITCH_1[MOVE_CTR+1],t_to_ground);
- if(ZONES_1[MOVE_CTR] == 1){
- dist_sz_temp <- min_corner(Pfx,sz_left_x,sz_front_y,sz_top_z,t_0,t_1);
- } else if(ZONES_1[MOVE_CTR] == 2){
- dist_sz_temp <- min_edge_yz(Pfx,sz_front_y,sz_top_z,t_0,t_1);
- } else if(ZONES_1[MOVE_CTR] == 3){
- dist_sz_temp <- min_corner(Pfx,sz_right_x,sz_front_y,sz_top_z,t_0,t_1);
- } else if(ZONES_1[MOVE_CTR] == 4){
- dist_sz_temp <- min_edge_xy(Pfx,sz_left_x,sz_front_y,t_0,t_1);
- } else if(ZONES_1[MOVE_CTR] == 5){
- dist_sz_temp <- min_face_y(Pfx,sz_front_y,t_0,t_1);
- } else if(ZONES_1[MOVE_CTR] == 6){
- dist_sz_temp <- min_edge_xy(Pfx,sz_right_x,sz_front_y,t_0,t_1);
- } else if(ZONES_1[MOVE_CTR] == 7){
- dist_sz_temp <- min_corner(Pfx,sz_left_x,sz_front_y,sz_bottom_z,t_0,t_1);
- } else if(ZONES_1[MOVE_CTR] == 8){
- dist_sz_temp <- min_edge_yz(Pfx,sz_front_y,sz_bottom_z,t_0,t_1);
- } else if(ZONES_1[MOVE_CTR] == 9){
- dist_sz_temp <- min_corner(Pfx,sz_right_x,sz_front_y,sz_bottom_z,t_0,t_1);
- }
- MOVE_CTR <- MOVE_CTR + 1;
- if (dist_sz_temp < dist_sz){
- dist_sz <- dist_sz_temp;
- stage <- 1;
- zone <- ZONES_1[MOVE_CTR-1];
- }
- if (dist_sz < ball_radius){
- OUT <- list(dist_sz = max(dist_sz-ball_radius,0), stage = stage, zone = zone, px = px, pz = pz);
- return(OUT);
- }
- }
- # Find the distances over STAGE 2
- if (STAGES > 1){
- MOVE_CTR <- 1;
- while(MOVE_CTR <= (MOVES_2+1) && SWITCH_2[MOVE_CTR] < t_to_ground){
- t_1 <- SWITCH_2[MOVE_CTR];
- t_2 <- min(SWITCH_2[MOVE_CTR+1],t_to_ground);
- if(ZONES_2[MOVE_CTR] == 1){
- dist_sz_temp <- min_edge_xz(Pfx,sz_left_x,sz_top_z,t_1,t_2);
- } else if(ZONES_2[MOVE_CTR] == 2){
- dist_sz_temp <- min_face_z(Pfx,sz_top_z,t_1,t_2);
- } else if(ZONES_2[MOVE_CTR] == 3){
- dist_sz_temp <- min_edge_xz(Pfx,sz_right_x,sz_top_z,t_1,t_2);
- } else if(ZONES_2[MOVE_CTR] == 4){
- dist_sz_temp <- min_face_x(Pfx,sz_left_x,t_1,t_2);
- } else if(ZONES_2[MOVE_CTR] == 5){
- dist_sz_temp <- 0;
- } else if(ZONES_2[MOVE_CTR] == 6){
- dist_sz_temp <- min_face_x(Pfx,sz_right_x,t_1,t_2);
- } else if(ZONES_2[MOVE_CTR] == 7){
- dist_sz_temp <- min_edge_xz(Pfx,sz_left_x,sz_bottom_z,t_1,t_2);
- } else if(ZONES_2[MOVE_CTR] == 8){
- dist_sz_temp <- min_face_z(Pfx,sz_bottom_z,t_1,t_2);
- } else if(ZONES_2[MOVE_CTR] == 9){
- dist_sz_temp <- min_edge_xz(Pfx,sz_right_x,sz_bottom_z,t_1,t_2);
- }
- MOVE_CTR <- MOVE_CTR + 1;
- if (dist_sz_temp < dist_sz){
- dist_sz <- dist_sz_temp;
- stage <- 2;
- zone <- ZONES_2[MOVE_CTR-1];
- }
- if (dist_sz < ball_radius){
- OUT <- list(dist_sz = max(dist_sz-ball_radius,0), stage = stage, zone = zone, px = px, pz = pz);
- return(OUT);
- }
- }
- }
- # Find the distances over STAGE 3
- if (STAGES > 2){
- MOVE_CTR <- 1;
- while(MOVE_CTR <= (MOVES_3+1) && SWITCH_3[MOVE_CTR] < t_to_ground){
- t_2 <- SWITCH_3[MOVE_CTR];
- t_3 <- min(SWITCH_3[MOVE_CTR+1],t_to_ground);
- if(ZONES_3[MOVE_CTR] == 1){
- dist_sz_temp <- min_corner(Pfx,sz_left_x,sz_back_y,sz_top_z,t_2,t_3);
- } else if(ZONES_3[MOVE_CTR] == 2){
- dist_sz_temp <- min_edge_yz(Pfx,sz_back_y,sz_top_z,t_2,t_3);
- } else if(ZONES_3[MOVE_CTR] == 3){
- dist_sz_temp <- min_corner(Pfx,sz_right_x,sz_back_y,sz_top_z,t_2,t_3);
- } else if(ZONES_3[MOVE_CTR] == 4){
- dist_sz_temp <- min_edge_xy(Pfx,sz_left_x,sz_back_y,t_2,t_3);
- } else if(ZONES_3[MOVE_CTR] == 5){
- dist_sz_temp <- min_face_y(Pfx,sz_back_y,t_2,t_3);
- } else if(ZONES_3[MOVE_CTR] == 6){
- dist_sz_temp <- min_edge_xy(Pfx,sz_right_x,sz_back_y,t_2,t_3);
- } else if(ZONES_3[MOVE_CTR] == 7){
- dist_sz_temp <- min_corner(Pfx,sz_left_x,sz_back_y,sz_bottom_z,t_2,t_3);
- } else if(ZONES_3[MOVE_CTR] == 8){
- dist_sz_temp <- min_edge_yz(Pfx,sz_back_y,sz_bottom_z,t_2,t_3);
- } else if(ZONES_3[MOVE_CTR] == 9){
- dist_sz_temp <- min_corner(Pfx,sz_right_x,sz_back_y,sz_bottom_z,t_2,t_3);
- }
- MOVE_CTR <- MOVE_CTR + 1;
- if (dist_sz_temp < dist_sz){
- dist_sz <- dist_sz_temp;
- stage <- 3;
- zone <- ZONES_3[MOVE_CTR-1];
- }
- if (dist_sz < ball_radius){
- OUT <- list(dist_sz = max(dist_sz-ball_radius,0), stage = stage, zone = zone, px = px, pz = pz);
- return(OUT);
- }
- }
- }
- OUT <- list(dist_sz = max(dist_sz-ball_radius,0), stage = stage, zone = zone, px = px, pz = pz);
- return(OUT);
- }
- ##################
- # 2D Strike Zone #
- ##################
- dist_2D_to_SZ <- function(Pfx){
- # This function finds the minimum distance from the pitch to the 2D strike zone
- # Pfx is a list containing ax, ay, az, vx0, vy0, vz0, x0, y0, z0, sz_top, and sz_bot
- # Set various locations in x, y, and z
- sz_front_y <- 17/12;
- plate_front <- 17/12;
- sz_left_x <- -17/24;
- sz_right_x <- 17/24;
- sz_top_z <- Pfx$sz_top;
- sz_bottom_z <- Pfx$sz_bot;
- ball_radius <- 0.125;
- # Time to the front of the strike zone
- t_to_front <- (-Pfx$vy0 - sqrt(Pfx$vy0^2 - 2*Pfx$ay*(Pfx$y0 - sz_front_y)))/Pfx$ay;
- # Time to the front of home plate
- t_to_plate <- (-Pfx$vy0 - sqrt(Pfx$vy0^2 - 2*Pfx$ay*(Pfx$y0 - plate_front)))/Pfx$ay;
- # Find the location/velocity at the front of the strike zone
- px <- x_eval(Pfx,t_to_front);
- pz <- z_eval(Pfx,t_to_front);
- vx <- vx_eval(Pfx,t_to_front);
- vz <- vz_eval(Pfx,t_to_front);
- px_plate <- x_eval(Pfx,t_to_plate);
- pz_plate <- z_eval(Pfx,t_to_plate);
- # Find the zone for the pitch at the front of the strike zone
- ZONE <- zone_check_2D(px,pz,vx,vz,sz_left_x,sz_right_x,sz_top_z,sz_bottom_z);
- # Find the distance to the front of the strike zone
- if(ZONE == 1){
- dist_sz <- sqrt((sz_left_x - px)^2 + (sz_top_z - pz)^2);
- } else if(ZONE == 2){
- dist_sz <- abs(sz_top_z - pz);
- } else if(ZONE == 3){
- dist_sz <- sqrt((sz_right_x - px)^2 + (sz_top_z - pz)^2);
- } else if(ZONE == 4){
- dist_sz <- abs(sz_left_x - px);
- } else if(ZONE == 5){
- dist_sz <- 0;
- } else if(ZONE == 6){
- dist_sz <- abs(sz_right_x - px);
- } else if(ZONE == 7){
- dist_sz <- sqrt((sz_left_x - px)^2 + (sz_bottom_z - pz)^2);
- } else if(ZONE == 8){
- dist_sz <- abs(sz_bottom_z - pz);
- } else if(ZONE == 9){
- dist_sz <- sqrt((sz_right_x - px)^2 + (sz_bottom_z - pz)^2);
- }
- if (pz < ball_radius){
- dist_sz <- 99999;
- }
- OUT <- list(dist_sz = max(dist_sz-ball_radius,0), zone = ZONE, px = px_plate, pz = pz_plate, vx = vx, vz = vz);
- return(OUT);
- }
- ###########################
- # 3D Strike Zone (Tunnel) #
- ###########################
- dist_3D_to_SZ_tunnel <- function(Pfx){
- # This function finds the minimum distance from the pitch to the strike zone (as a tunnel to the catcher's mitt) in three dimensions
- # Pfx is a list containing ax, ay, az, vx0, vy0, vz0, x0, y0, z0, sz_top, and sz_bot
- # Set various locations in x, y, and z
- sz_front_y <- 17/12;
- mitt_y <- -55/24;
- ground_z <- 0.125;
- sz_left_x <- -17/24;
- sz_right_x <- 17/24;
- sz_top_z <- Pfx$sz_top;
- sz_bottom_z <- Pfx$sz_bot;
- ball_radius <- 0.125;
- # Find the time to various distances in y
- # STAGE 1: Time to the front of home plate
- t_to_front <- (-Pfx$vy0 - sqrt(Pfx$vy0^2 - 2*Pfx$ay*(Pfx$y0 - sz_front_y)))/Pfx$ay;
- # Time to catcher's mitt
- t_to_mitt <- (-Pfx$vy0 - sqrt(Pfx$vy0^2 - 2*Pfx$ay*(Pfx$y0 - mitt_y)))/Pfx$ay;
- # Time to ball hitting ground
- disc_z <- Pfx$vz0^2 - 2*Pfx$az*(Pfx$z0 - ground_z);
- if (disc_z > 0){
- t_to_ground <- (-Pfx$vz0 - sqrt(disc_z))/Pfx$az;
- } else {
- t_to_ground <- t_to_mitt + 1;
- }
- # Find the location at the front of the strike zone
- px <- x_eval(Pfx,t_to_mitt);
- pz <- z_eval(Pfx,t_to_mitt);
- # Find the number of stages before the ball hits the ground OR the catcher's mitt
- if(t_to_ground > t_to_front){
- STAGES <- 2;
- } else {
- STAGES <- 1;
- }
- # Allocate space for times when the pitch switches zones
- ZONE_TIMES <- array(0,dim=8);
- # Left Vertical
- disc_LV <- Pfx$vx0^2 - 2*Pfx$ax*(Pfx$x0 - sz_left_x);
- if (disc_LV > 0 && Pfx$ax != 0) {
- ZONE_TIMES[1] <- (-Pfx$vx0 + sqrt(disc_LV))/Pfx$ax;
- ZONE_TIMES[2] <- (-Pfx$vx0 - sqrt(disc_LV))/Pfx$ax;
- } else if (Pfx$ax == 0) {
- ZONE_TIMES[1] <- -(Pfx$x0-sz_left_x)/Pfx$vx0;
- }
- # Right Vertical
- disc_RV <- Pfx$vx0^2 - 2*Pfx$ax*(Pfx$x0 - sz_right_x);
- if (disc_RV > 0 && Pfx$ax != 0) {
- ZONE_TIMES[3] <- (-Pfx$vx0 + sqrt(disc_RV))/Pfx$ax;
- ZONE_TIMES[4] <- (-Pfx$vx0 - sqrt(disc_RV))/Pfx$ax;
- } else if (Pfx$ax == 0) {
- ZONE_TIMES[3] <- -(Pfx$x0-sz_right_x)/Pfx$vx0;
- }
- # Top Horizontal
- disc_TH <- Pfx$vz0^2 - 2*Pfx$az*(Pfx$z0 - sz_top_z);
- if (disc_TH > 0 && Pfx$az != 0) {
- ZONE_TIMES[5] <- (-Pfx$vz0 + sqrt(disc_TH))/Pfx$az;
- ZONE_TIMES[6] <- (-Pfx$vz0 - sqrt(disc_TH))/Pfx$az;
- } else if (Pfx$az == 0) {
- ZONE_TIMES[5] <- -(Pfx$z0-sz_top_z)/Pfx$vz0;
- }
- # Bottom Horizontal
- disc_BH <- Pfx$vz0^2 - 2*Pfx$az*(Pfx$z0 - sz_bottom_z);
- if (disc_BH > 0 && Pfx$az != 0) {
- ZONE_TIMES[7] <- (-Pfx$vz0 + sqrt(disc_BH))/Pfx$az;
- ZONE_TIMES[8] <- (-Pfx$vz0 - sqrt(disc_BH))/Pfx$az;
- } else if (Pfx$az == 0) {
- ZONE_TIMES[7] <- -(Pfx$z0-sz_bottom_z)/Pfx$vz0;
- }
- # Allocate arrays for moves between the zones
- ZONE_MOVE_1 <- array(0,dim=8);
- ZONE_MOVE_2 <- array(0,dim=8);
- ZONE_TIMES_1 <- array(0,dim=8);
- ZONE_TIMES_2 <- array(0,dim=8);
- # Check for times within range of 50 feet to the middle of the strike zone
- for(i in 1:8){
- if(ZONE_TIMES[i] > 0 && ZONE_TIMES[i] < t_to_front) {
- ZONE_MOVE_1[i] <- 1;
- ZONE_TIMES_1[i] <- ZONE_TIMES[i];
- }
- if(ZONE_TIMES[i] > t_to_front && ZONE_TIMES[i] < t_to_mitt) {
- ZONE_MOVE_2[i] <- 1;
- ZONE_TIMES_2[i] <- ZONE_TIMES[i];
- }
- }
- # Sort the times for zone switches and their indices
- ZONE_TIMES_1_SORT <- sort(ZONE_TIMES_1,decreasing=FALSE,index.return=TRUE);
- ZONE_TIMES_2_SORT <- sort(ZONE_TIMES_2,decreasing=FALSE,index.return=TRUE);
- MOVES_1 <- sum(ZONE_MOVE_1);
- MOVES_2 <- sum(ZONE_MOVE_2);
- ZONES_1 <- array(0,dim=(MOVES_1+1));
- ZONES_2 <- array(0,dim=(MOVES_2+1));
- SWITCH_1 <- array(0,dim=(MOVES_1+2));
- SWITCH_2 <- array(0,dim=(MOVES_2+2));
- # Find the zone in which the pitch starts
- ZONES_1[1] <- zone_check(Pfx,sz_left_x,sz_right_x,sz_top_z,sz_bottom_z);
- SWITCH_1[1] <- 0;
- k <- 1;
- for(i in ZONE_TIMES_1_SORT$ix){
- if(ZONE_MOVE_1[i] == 1){
- k <- k+1;
- if(i <= 4){
- vx <- vx_eval(Pfx,ZONE_TIMES_1[i]);
- if(vx > 0){
- ZONES_1[k] <- ZONES_1[k-1] + 1;
- } else {
- ZONES_1[k] <- ZONES_1[k-1] - 1;
- }
- } else {
- vz <- vz_eval(Pfx,ZONE_TIMES_1[i]);
- if(vz > 0){
- ZONES_1[k] <- ZONES_1[k-1] - 3;
- } else {
- ZONES_1[k] <- ZONES_1[k-1] + 3;
- }
- }
- SWITCH_1[k] <- ZONE_TIMES_1[i];
- }
- }
- SWITCH_1[MOVES_1+2] <- t_to_front;
- ZONES_2[1] <- ZONES_1[MOVES_1+1];
- SWITCH_2[1] <- t_to_front;
- k <- 1;
- for(i in ZONE_TIMES_2_SORT$ix){
- if(ZONE_MOVE_2[i] == 1){
- k <- k+1;
- if(i <= 4){
- vx <- vx_eval(Pfx,ZONE_TIMES_2[i]);
- if(vx > 0){
- ZONES_2[k] <- ZONES_2[k-1] + 1;
- } else {
- ZONES_2[k] <- ZONES_2[k-1] - 1;
- }
- } else {
- vz <- vz_eval(Pfx,ZONE_TIMES_2[i]);
- if(vz > 0){
- ZONES_2[k] <- ZONES_2[k-1] - 3;
- } else {
- ZONES_2[k] <- ZONES_2[k-1] + 3;
- }
- }
- SWITCH_2[k] <- ZONE_TIMES_2[i];
- }
- }
- SWITCH_2[MOVES_2+2] <- t_to_mitt;
- MOVE_CTR <- 1;
- dist_sz <- 55;
- # Find the distances over STAGE 1
- while(MOVE_CTR <= (MOVES_1+1) && SWITCH_1[MOVE_CTR] < t_to_ground){
- t_0 <- SWITCH_1[MOVE_CTR];
- t_1 <- min(SWITCH_1[MOVE_CTR+1],t_to_ground);
- if(ZONES_1[MOVE_CTR] == 1){
- dist_sz_temp <- min_corner(Pfx,sz_left_x,sz_front_y,sz_top_z,t_0,t_1);
- } else if(ZONES_1[MOVE_CTR] == 2){
- dist_sz_temp <- min_edge_yz(Pfx,sz_front_y,sz_top_z,t_0,t_1);
- } else if(ZONES_1[MOVE_CTR] == 3){
- dist_sz_temp <- min_corner(Pfx,sz_right_x,sz_front_y,sz_top_z,t_0,t_1);
- } else if(ZONES_1[MOVE_CTR] == 4){
- dist_sz_temp <- min_edge_xy(Pfx,sz_left_x,sz_front_y,t_0,t_1);
- } else if(ZONES_1[MOVE_CTR] == 5){
- dist_sz_temp <- min_face_y(Pfx,sz_front_y,t_0,t_1);
- } else if(ZONES_1[MOVE_CTR] == 6){
- dist_sz_temp <- min_edge_xy(Pfx,sz_right_x,sz_front_y,t_0,t_1);
- } else if(ZONES_1[MOVE_CTR] == 7){
- dist_sz_temp <- min_corner(Pfx,sz_left_x,sz_front_y,sz_bottom_z,t_0,t_1);
- } else if(ZONES_1[MOVE_CTR] == 8){
- dist_sz_temp <- min_edge_yz(Pfx,sz_front_y,sz_bottom_z,t_0,t_1);
- } else if(ZONES_1[MOVE_CTR] == 9){
- dist_sz_temp <- min_corner(Pfx,sz_right_x,sz_front_y,sz_bottom_z,t_0,t_1);
- }
- MOVE_CTR <- MOVE_CTR + 1;
- if (dist_sz_temp < dist_sz){
- dist_sz <- dist_sz_temp;
- stage <- 1;
- zone <- ZONES_1[MOVE_CTR-1];
- }
- if (dist_sz < ball_radius){
- OUT <- list(dist_sz = max(0,dist_sz-ball_radius), stage = 1, zone = zone, px = px, pz = pz);
- return(OUT);
- }
- }
- # Find the distances over STAGE 2
- if (STAGES > 1){
- MOVE_CTR <- 1;
- while(MOVE_CTR <= (MOVES_2+1) && SWITCH_2[MOVE_CTR] < t_to_ground){
- t_1 <- SWITCH_2[MOVE_CTR];
- t_2 <- min(SWITCH_2[MOVE_CTR+1],t_to_ground);
- if(ZONES_2[MOVE_CTR] == 1){
- dist_sz_temp <- min_edge_xz(Pfx,sz_left_x,sz_top_z,t_1,t_2);
- } else if(ZONES_2[MOVE_CTR] == 2){
- dist_sz_temp <- min_face_z(Pfx,sz_top_z,t_1,t_2);
- } else if(ZONES_2[MOVE_CTR] == 3){
- dist_sz_temp <- min_edge_xz(Pfx,sz_right_x,sz_top_z,t_1,t_2);
- } else if(ZONES_2[MOVE_CTR] == 4){
- dist_sz_temp <- min_face_x(Pfx,sz_left_x,t_1,t_2);
- } else if(ZONES_2[MOVE_CTR] == 5){
- dist_sz_temp <- 0;
- } else if(ZONES_2[MOVE_CTR] == 6){
- dist_sz_temp <- min_face_x(Pfx,sz_right_x,t_1,t_2);
- } else if(ZONES_2[MOVE_CTR] == 7){
- dist_sz_temp <- min_edge_xz(Pfx,sz_left_x,sz_bottom_z,t_1,t_2);
- } else if(ZONES_2[MOVE_CTR] == 8){
- dist_sz_temp <- min_face_z(Pfx,sz_bottom_z,t_1,t_2);
- } else if(ZONES_2[MOVE_CTR] == 9){
- dist_sz_temp <- min_edge_xz(Pfx,sz_right_x,sz_bottom_z,t_1,t_2);
- }
- MOVE_CTR <- MOVE_CTR + 1;
- if (dist_sz_temp < dist_sz){
- dist_sz <- dist_sz_temp;
- stage <- 2;
- zone <- ZONES_2[MOVE_CTR-1];
- }
- if (dist_sz < ball_radius){
- OUT <- list(dist_sz = max(0,dist_sz-ball_radius), stage = 2, zone = zone, px = px, pz = pz);
- return(OUT);
- }
- }
- }
- OUT <- list(dist_sz = max(0,dist_sz-ball_radius), stage = stage, zone = zone, px = px, pz = pz);
- return(OUT);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement