Nothing
#' Create a density in 2-dimensions
#'
#' @param bp object of class `biplot`
#' @param which which group to create a density; limited to only a single group at a time.
#' If NULL, density drawn over all data points.
#' @param contours logical indicating whether contours are added to the density plot
#' @param h vector of bandwidths for x and y directions, see \code{\link[MASS]{kde2d}}.
#' @param n number of grid points in each direction. Can be scalar or a length-2 integer
#' vector.
#' @param col vector of colours to use to form a 'continuous' sequence of colours.
#' @param contour.col colour of the contours.
#' @param cuts number of colours in `col`.
#' @param cex character expansion.
#' @param tcl The length of tick marks as a fraction of the height of a line of text.
#' @param mgp The margin line.
#' @param layout.heights A vector of values for the heights of rows.
#' @param legend.mar The margin line of the legend.
#'
#' @return An object of class \code{biplot}.
#' @export
#'
#' @examples
#' biplot(iris[,1:4],group.aes = iris[,5]) |> PCA() |>
#' density2D(which=3,col=c("white","purple","cyan","blue")) |> plot()
#' biplot(iris[,1:4],group.aes = iris[,5]) |> PCA() |>
#' density2D(which=3,col=c("white","purple","cyan","blue"),contours = TRUE,
#' contour.col = "grey") |> plot()
density2D <- function(bp,which = NULL,contours = F, h = NULL, n = 100,
col = c("green", "yellow", "red"), contour.col = "black", cuts = 50, cex = 0.6,
tcl = -0.2, mgp = c(0, -0.25, 0), layout.heights = c(100, 10), legend.mar = c(2, 5, 0, 5))
{
g <- bp$g
g.names <- bp$g.names
# If which = NULL, draw density over all groups
if (is.null(which))
{
which <- 1
G <- indmat(rep(1,bp$n))
print("Density plotted over all samples")
} else G <- indmat(bp$group.aes)
if(length(which) > 1)
{
which <- which[1]
print("Density drawn for the first group")
}
density.style <- biplot.density.2D.control(g=g, g.names=g.names, which=which,
contours=contours, h=h,
n=n,col=col,contour.col=grDevices::adjustcolor(contour.col,0.6),
cuts=cuts, cex=cex,tcl=tcl,mgp=mgp,
layout.heights = layout.heights,
legend.mar=legend.mar)
mat <- bp$Z[G[, which] == 1, ]
x.range <- range(bp$Z[, 1])
y.range <- range(bp$Z[, 2])
width <- max(x.range[2] - x.range[1], y.range[2] - y.range[1])
xlim <- mean(bp$Z[, 1]) + c(-1, 1) * 0.75 * width
ylim <- mean(bp$Z[, 1]) + c(-1, 1) * 0.75 * width
if (is.null(density.style$h)) z.density <- MASS::kde2d(mat[, 1], mat[, 2], n = density.style$n, lims = c(xlim, ylim))
else z.density <- MASS::kde2d(mat[, 1], mat[, 2], h = density.style$h, n = density.style$n, lims = c(xlim, ylim))
if(length(density.style$col)==1) density.style$col <- c("white",density.style$col)
bp$z.density <- z.density
bp$density.style <- density.style
bp
}
#' Creates a kernel density in 1-dimension
#'
#' @param bp object of class `biplot`
#' @param which which group.
#' @param h bandwidth.
#' @param kernel character string giving the smoothing kernel to be used.
#' @param col colours to be used for each of the density curves.
#' @param lwd linewidth of density curve.
#' @param legend.mar The margin line of the legend.
#'
#' @return An object of class \code{biplot}.
#' @export
#'
#' @examples biplot (iris,classes=iris[,5]) |> CVA(dim=1) |> density1D() |> plot()
density1D <- function(bp,which = NULL, h = "nrd0", kernel="gaussian",
col = ez.col, lwd=1.5,
legend.mar = c(2, 5, 0, 5))
{
g <- bp$g
g.names <- bp$g.names
if (is.null(which)) which <- 1:g
G <- indmat(bp$group.aes)
tmp.g <- length(which)
if (length(lwd)==tmp.g){lwd.vec <- lwd} else {lwd.vec <- rep(lwd,bp$g)}
density.style <- list(g=g, g.names=g.names[which], which=which,
h=h,col=col[which],lwd=lwd.vec[which],
legend.mar=legend.mar)
z.density <- vector("list", bp$g)
z.density.max <- numeric(bp$g)
for (i in 1:tmp.g) {
j <- which[i]
mat <- bp$Z[G[, j] == 1]
if(is.numeric(h)){
z.density[[i]] <- stats::density(mat, width=h, kernel=kernel)
} else {z.density[[i]] <- stats::density(mat, bw=h, kernel=kernel)}
z.density.max[i] <- max(z.density[[i]]$y)
}
maxy <- max(z.density.max)
for (j in 1:tmp.g) {
y.dens <- z.density[[j]]$y
z.density[[j]]$y <- (y.dens)/(maxy)*2.5
}
bp$z.density <- z.density
bp$density.style <- density.style
bp
}
# ----------------------------------------------------------------------------------------------
#' Create alpha bags
#'
#' @description
#' This function produces \eqn{\alpha}-bags, which is a useful graphical summary of the
#' scatter plot. The alpha-bag refers to a contour which contains \eqn{\alpha}% of the observations.
#'
#' @param bp an object of class \code{biplot}.
#' @param alpha numeric vector between 0 and 1 to determine coverage of the bag (\eqn{\alpha}), with default \code{0.95}.
#' @param which numeric vector indicating the selection of groups or classes to be fitted with \eqn{\alpha}-bags.
#' @param col vector of colours for the \eqn{\alpha}-bags. Multiple \eqn{\alpha} bags for one group will be displayed in the same colour.
#' @param lty vector of line types for the \eqn{\alpha}-bags. The same line type will be used per value of \eqn{\alpha}.
#' @param lwd vector of line widths for the \eqn{\alpha}-bags. The same line width will be used per value of \eqn{\alpha}.
#' @param max maximum number of samples to include in \eqn{\alpha}-bag calculations, with default 2500. If
#' more samples are in the group, a random sample of size max is taken for the computations.
#' @param trace logical, indicating progress of computation.
#' @param opacity level of opacity, with default \code{0.5}.
#' @param outlying logical indicating whether only outlying points should be plotted. Note the \code{which} argument may be overwritten when \code{TRUE}
#'
#' @return A list with the following components is available:
#' \item{alpha.bags}{list of coordinates for the \eqn{\alpha}-bags for each group.}
#' \item{col}{vector of colours for the \eqn{\alpha}-bags.}
#' \item{lty}{vector of line types for the \eqn{\alpha}-bags.}
#' \item{lwd}{vector of line widths for the \eqn{\alpha}-bags.}
#'
#' @references
#' Gower, J., Gardner-Lubbe, S. & Le Roux, N. (2011, ISBN: 978-0-470-01255-0) \emph{Understanding Biplots.} Chichester, England: John Wiley & Sons Ltd.
#'
#' @export
#' @usage alpha.bags(bp, alpha = 0.95, which = NULL, col = ez.col[which], lty = 1,
#' lwd = 1, max = 2500, trace = TRUE, opacity = 0.25, outlying=FALSE)
#' @aliases alpha.bags
#'
#' @examples
#' biplot (iris[,1:4]) |> PCA(group.aes=iris[,5]) |> alpha.bags(alpha=0.95) |> plot()
#' biplot (iris[,1:4],group.aes=iris[,5]) |> PCA() |> alpha.bags(alpha=0.95) |> plot()
#'
alpha.bags <- function(bp, alpha=0.95, which = NULL, col = ez.col[which], lty = 1,
lwd = 1, max = 2500, trace = TRUE, opacity = 0.25,
outlying=FALSE)
{
g <- bp$g
g.names <- bp$g.names
if (is.null(which)) which <- 1:g
#This piece of code is just to ensure which arguments in samples() and alpha.bag() lines up
# to plot only the specified alpha bags and points
if(!is.null(bp$samples$which) & outlying){
if(length(which) != length(bp$samples$which)){
message("NOTE in alpha.bags(): 'which' argument overwritten in samples()")
which<-bp$samples$which
}
else if(all(sort(which) != sort(bp$alpha.bag.aes$which))){
message("NOTE in alpha.bags(): 'which' argument overwritten in samples()")
which<-bp$samples$which
}
}
control.output <- control.alpha.bags(g=g, g.names=g.names, alpha=alpha, which=which,
col=col, lty=lty, lwd=lwd, max=max, opacity=opacity)
all.alpha.bags <- list()
samples_outside<-list()
for(a in 1:length(control.output$which))
{
if (trace)
cat(paste("Computing", control.output$alpha[a], "-bag for",g.names[control.output$which[a]], "\n"))
Zgroup <- bp$Z[bp$group.aes==g.names[control.output$which[a]],]
if(ncol(bp$Z)==2){
calc <- calc.alpha.bags(Zgroup, aa=control.output$alpha[a], approx.limit=control.output$max)$xy[,1:2]
new_hull<-geometry::convhulln(calc)
samples_outside[[a]]<-!geometry::inhulln(new_hull,Zgroup)
} else if(ncol(bp$Z)==1){
calc <- stats::quantile(Zgroup, c((1 - control.output$alpha[a])/2, 1 - (1 - control.output$alpha[a])/2))
} else {
warning("Alpha Bags only available for biplots of fewer than three dimensions.");calc <- NA
}
all.alpha.bags[[a]] <- calc
}
names(all.alpha.bags) <- paste (g.names[control.output$which], control.output$alpha, sep="-")
if (is.null(bp$alpha.bags)) bp$alpha.bags <- all.alpha.bags
else bp$alpha.bags <- append(bp$alpha.bags, all.alpha.bags)
if (is.null(bp$alpha.bag.aes)) bp$alpha.bag.aes <- list(col=control.output$col,
lty=control.output$lty,
lwd=control.output$lwd,
opacity=control.output$opacity)
else { bp$alpha.bag.aes$col <- c(bp$alpha.bag.aes$col, control.output$col)
bp$alpha.bag.aes$lty <- c(bp$alpha.bag.aes$lty, control.output$lty)
bp$alpha.bag.aes$lwd <- c(bp$alpha.bag.aes$lwd, control.output$lwd)
bp$alpha.bag.aes$opacity <- c(bp$alpha.bag.aes$opacity, control.output$opacity)
}
if(outlying)
bp$alpha.bag.outside<-samples_outside
bp$alpha.bag.aes$which<-which
bp
}
# ----------------------------------------------------------------------------------------------
#' Concentration ellipses (\eqn{\kappa}-ellipses)
#'
#' @description
#' This function produces \eqn{\kappa}-ellipses, which is a useful geometrical description of the
#' data points about the sample mean.
#'
#' @param bp an object of class \code{biplot}.
#' @param df degrees of freedom, with default \code{2}.
#' @param kappa value to construct \eqn{\kappa}-ellipse (the value of \eqn{\kappa}).
#' @param which the selection of the group for ellipse construction.
#' @param alpha size of \eqn{\alpha}-bag, with default \code{0.95}.
#' @param col colour of ellipse. Multiple \eqn{\kappa}-ellipse for one group will be displayed in the same colour.
#' @param lty line type of ellipse. The same line type will be used per value of \eqn{\kappa}.
#' @param lwd line width of ellipse. The same line width will be used per value of \eqn{\kappa}.
#' @param opacity level of opacity, with default \code{0.25}.
#' @param trace logical, indicating progress of computation.
#'
#' @return A list with the following components is available:
#' \item{conc.ellipses}{list of coordinates for the \eqn{\kappa}-ellipses for each group.}
#' \item{col}{vector of colours for the \eqn{\kappa}-ellipses.}
#' \item{lty}{vector of line types for the \eqn{\kappa}-ellipses.}
#' \item{lwd}{vector of line widths for the \eqn{\kappa}-ellipses.}
#' \item{alpha}{vector of \eqn{\alpha} values.}
#'
#' @references
#' Gower, J., Gardner-Lubbe, S. & Le Roux, N. (2011, ISBN: 978-0-470-01255-0) \emph{Understanding Biplots.} Chichester, England: John Wiley & Sons Ltd.<br><br>
#' @export
#' @usage ellipses(bp, df=2, kappa = NULL, which = NULL,
#' alpha = 0.95, col = bp$sample$col[which], lty = 1, lwd = 1,
#' opacity = 0.25, trace = TRUE)
#' @aliases ellipses
#'
#' @examples
#' biplot (iris[,1:4]) |> PCA(group.aes=iris[,5]) |> ellipses(kappa=2) |> plot()
#'
ellipses <- function(bp, df=2, kappa = NULL, which = NULL, alpha = 0.95,
col = bp$sample$col[which], lty = 1, lwd = 1, opacity = 0.25, trace = TRUE)
{
g <- bp$g
g.names <- bp$g.names
if (ncol(bp$Z)!=2) df <- ncol(bp$Z)
if (is.null(which)) which <- 1:g
if (any(alpha < 0 | alpha > 0.99)) stop(message = "alpha not to be negative or larger than 0.99")
if (is.null(kappa)) kappa <- sqrt(stats::qchisq(alpha,df))
control.output <- control.concentration.ellipse (g=g, g.names=g.names, df=df, kappa = kappa, which = which,
col = col, lty = lty, lwd = lwd,
opacity = opacity)
all.ellipses <- list()
for(a in 1:length(control.output$which))
{
if (trace) cat (paste("Computing", round(control.output$kappa[a],2), "-ellipse for",g.names[control.output$which[a]], "\n"))
Zgroup <- bp$Z[bp$group.aes==g.names[control.output$which[a]],]
if(ncol(bp$Z)==2){calc <- calc.concentration.ellipse(Zgroup, kappa=control.output$kappa[a])
} else if(ncol(bp$Z)==1){
calc <- c(-control.output$kappa[a], control.output$kappa[a])*stats::sd(Zgroup)+mean(Zgroup)
} else if(ncol(bp$Z)==3) {
calc <- rgl::ellipse3d(x = stats::var(Zgroup), centre = apply(Zgroup, 2, mean), t = control.output$kappa[a])
# warning("Ellipses currently only available for biplots of fewer than three dimensions.");calc <- NA
}
all.ellipses[[a]] <- calc
}
names(all.ellipses) <- paste (g.names[control.output$which], round(control.output$kappa,2), sep="-")
if (is.null(bp$conc.ellipses)) bp$conc.ellipses <- all.ellipses
else bp$conc.ellipses <- append(bp$conc.ellipses, all.ellipses)
if (is.null(bp$conc.ellipse.aes)) bp$conc.ellipse.aes <- list(col=control.output$col,
lty=control.output$lty,
lwd=control.output$lwd,
opacity=control.output$opacity)
else { bp$conc.ellipse.aes$col <- c(bp$conc.ellipse.aes$col, control.output$col)
bp$conc.ellipse.aes$lty <- c(bp$conc.ellipse.aes$lty, control.output$lty)
bp$conc.ellipse.aes$lwd <- c(bp$conc.ellipse.aes$lwd, control.output$lwd)
bp$conc.ellipse.aes$opacity <- c(bp$conc.ellipse.aes$opacity, control.output$opacity)
}
bp
}
# ----------------------------------------------------------------------------------------------
#' Calculate concentration ellipses
#'
#' @param X matrix of coordinates.
#' @param kappa quantile of the chi-squared distribution determining the size of the ellipse.
#' @param covmat a covariance matrix to use in place of computing a covariance matrix from X.
#'
#' @return matrix of coordinates.
#'
#' @noRd
calc.concentration.ellipse <- function (X, kappa=2, covmat = NULL)
{
means <- matrix(apply(X, 2, mean), nrow = 2)
if (is.null(covmat)) covmat <- stats::cov(X)
range.vec <- apply(X, 2, range)
mid.vec <- apply(range.vec, 2, function(x) (x[2] + x[1])/2)
dif <- max(range.vec[2, ] - range.vec[1, ])/2
xlim <- c(mid.vec[1] - dif, mid.vec[1] + dif)
ylim <- c(mid.vec[2] - dif, mid.vec[2] + dif)
svd.covmat <- svd(covmat)
a <- (0:628)/100 # 2pi100 = 628.3185
Y <- cbind(cos(a), sin(a))
Y <- Y %*% diag(sqrt(svd.covmat$d)) %*% t(svd.covmat$v) * kappa
Y + matrix(rep(1, 629), ncol = 1) %*% t(means)
}
# ----------------------------------------------------------------------------------------------
#' Calculate alpha bags
#'
#' @param x,y,aa,na.rm,approx.limit,precision see arguments of function `compute.bagplot` in the R package `aplpack`
#' @return a list with an xy component
#' @importFrom grDevices chull
#' @noRd
#'
calc.alpha.bags <- function (x, y, aa=0.95, na.rm = TRUE, approx.limit = 2500, precision = 1)
{
# based on the function compute.bagplot
# from the R package aplpack
# Wolf H (2019). _aplpack: Another Plot Package (version 190512)_. <URL: https://cran.r-project.org/package=aplpack>.
win <- function(dx, dy) { atan2(y = dy, x = dx) }
out.of.polygon <- function(xy, pg) {
xy <- matrix(xy, ncol = 2)
if (nrow(pg) == 1) return(xy[, 1] == pg[1] & xy[, 2] == pg[2])
m <- nrow(xy)
n <- nrow(pg)
limit <- -abs(1e-10 * diff(range(pg)))
pgn <- cbind(diff(c(pg[, 2], pg[1, 2])), -diff(c(pg[,1], pg[1, 1])))
S <- colMeans(xy)
dxy <- cbind(S[1] - pg[, 1], S[2] - pg[, 2])
if (!all(limit < apply(dxy * pgn, 1, sum))) {
pg <- pg[n:1, ]
pgn <- -pgn[n:1, ]
}
in.pg <- rep(TRUE, m)
for (j in 1:n) {
dxy <- xy - matrix(pg[j, ], m, 2, byrow = TRUE)
in.pg <- in.pg & limit < (dxy %*% pgn[j, ])
}
return(!in.pg)
}
cut.z.pg <- function(zx, zy, p1x, p1y, p2x, p2y) {
a2 <- (p2y - p1y)/(p2x - p1x)
a1 <- zy/zx
sx <- (p1y - a2 * p1x)/(a1 - a2)
sy <- a1 * sx
sxy <- cbind(sx, sy)
h <- any(is.nan(sxy)) || any(is.na(sxy)) || any(Inf == abs(sxy))
if (h) {
h <- 0 == zx
sx <- ifelse(h, zx, sx)
sy <- ifelse(h, p1y - a2 * p1x, sy)
a1 <- ifelse(abs(a1) == Inf, sign(a1) * 123456789 * 1e+10, a1)
a2 <- ifelse(abs(a2) == Inf, sign(a2) * 123456789 * 1e+10, a2)
h <- 0 == (a1 - a2) & sign(zx) == sign(p1x)
sx <- ifelse(h, p1x, sx)
sy <- ifelse(h, p1y, sy)
h <- 0 == (a1 - a2) & sign(zx) != sign(p1x)
sx <- ifelse(h, p2x, sx)
sy <- ifelse(h, p2y, sy)
h <- p1x == p2x & zx != p1x & p1x != 0
sx <- ifelse(h, p1x, sx)
sy <- ifelse(h, zy * p1x/zx, sy)
h <- p1x == p2x & zx != p1x & p1x == 0
sx <- ifelse(h, p1x, sx)
sy <- ifelse(h, 0, sy)
h <- p1x == p2x & zx == p1x & p1x != 0
sx <- ifelse(h, zx, sx)
sy <- ifelse(h, zy, sy)
h <- p1x == p2x & zx == p1x & p1x == 0 & sign(zy) == sign(p1y)
sx <- ifelse(h, p1x, sx)
sy <- ifelse(h, p1y, sy)
h <- p1x == p2x & zx == p1x & p1x == 0 & sign(zy) != sign(p1y)
sx <- ifelse(h, p1x, sx)
sy <- ifelse(h, p2y, sy)
h <- zx == p1x & zy == p1y
sx <- ifelse(h, p1x, sx)
sy <- ifelse(h, p1y, sy)
h <- zx == p2x & zy == p2y
sx <- ifelse(h, p2x, sx)
sy <- ifelse(h, p2y, sy)
h <- zx == 0 & zy == 0
sx <- ifelse(h, 0, sx)
sy <- ifelse(h, 0, sy)
sxy <- cbind(sx, sy)
}
return(sxy)
}
find.cut.z.pg <- function(z, pg, center = c(0, 0)) {
if (!is.matrix(z)) z <- rbind(z)
if (1 == nrow(pg)) return(matrix(center, nrow(z), 2, TRUE))
n.pg <- nrow(pg)
n.z <- nrow(z)
z <- cbind(z[, 1] - center[1], z[, 2] - center[2])
pgo <- pg
pg <- cbind(pg[, 1] - center[1], pg[, 2] - center[2])
apg <- win(pg[, 1], pg[, 2])
apg[is.nan(apg)] <- 0
a <- order(apg)
apg <- apg[a]
pg <- pg[a, ]
az <- win(z[, 1], z[, 2])
segm.no <- apply((outer(apg, az, "<")), 2, sum)
segm.no <- ifelse(segm.no == 0, n.pg, segm.no)
next.no <- 1 + (segm.no%%length(apg))
cuts <- cut.z.pg(z[, 1], z[, 2], pg[segm.no, 1], pg[segm.no,2], pg[next.no, 1], pg[next.no, 2])
cuts <- cbind(cuts[, 1] + center[1], cuts[, 2] + center[2])
return(cuts)
}
hdepth.of.points <- function(tp) {
n.tp <- nrow(tp)
tphdepth <- rep(0, n.tp)
dpi <- 2 * pi - 1e-06
for (j in 1:n.tp) {
dx <- tp[j, 1] - xy[, 1]
dy <- tp[j, 2] - xy[, 2]
a <- win(dx, dy) + pi
h <- a < 10
a <- a[h]
ident <- sum(!h)
init <- sum(a < pi)
a.shift <- (a + pi)%%dpi
minusplus <- c(rep(-1, length(a)), rep(1, length(a)))
h <- cumsum(minusplus[order(c(a, a.shift))])
tphdepth[j] <- init + min(h) + 1
}
tphdepth
}
find.hdepths.tp <- function (tp, data, number.of.directions = 181)
{
xy <- as.matrix(data)
tp <- as.matrix(rbind(tp))
n.tp <- dim(tp)[1]
for (j in 1:2) {
xy[, j] <- xy[, j] - (h <- min(xy[, j], na.rm = TRUE))
tp[, j] <- tp[, j] - h
if (0 < (h <- max(xy[, j], na.rm = TRUE))) {
xy[, j] <- xy[, j]/h
tp[, j] <- tp[, j]/h
}
}
phi <- c(seq(0, 180, length = number.of.directions)[-1] * (2 * pi/360))
sinphi <- c(sin(phi), 1)
cosphi <- c(cos(phi), 0)
RM1 <- round(digits = 6, rbind(cosphi, sinphi))
hdtp <- rep(length(xy[, 1]), length(tp[, 1]))
for (j in seq(along = sinphi)) {
xyt <- xy %*% RM1[, j]
tpt <- (tp %*% RM1[, j])[]
xyt <- xyt[!is.na(xyt)]
hdtp <- pmin(hdtp, (rank(c(tpt, xyt), ties.method = "min"))[1:n.tp] - rank(tpt, ties.method = "min"),
rank(-c(tpt, xyt), ties.method = "min")[1:n.tp] - rank(-tpt, ties.method = "min"))
}
hdtp
}
expand.hull <- function(pg, k) {
if (1 >= nrow(pg)) return(pg)
resolution <- floor(20 * precision)
pg0 <- xy[hdepth == 1, ]
pg0 <- pg0[chull(pg0[, 1], pg0[, 2]), ]
end.points <- find.cut.z.pg(pg, pg0, center = center)
lam <- ((0:resolution)^1)/resolution^1
pg.new <- pg
for (i in 1:nrow(pg)) {
tp <- cbind(pg[i, 1] + lam * (end.points[i, 1] - pg[i, 1]), pg[i, 2] + lam * (end.points[i, 2] - pg[i, 2]))
hd.tp <- find.hdepths.tp(tp, xy)
ind <- max(sum(hd.tp >= k), 1)
if (ind < length(hd.tp)) {
tp <- cbind(tp[ind, 1] + lam * (tp[ind + 1, 1] - tp[ind, 1]), tp[ind, 2] + lam * (tp[ind + 1, 2] - tp[ind, 2]))
hp.tp <- find.hdepths.tp(tp, xy)
ind <- max(sum(hd.tp >= k), 1)
}
pg.new[i, ] <- tp[ind, ]
}
pg.new <- pg.new[chull(pg.new[, 1], pg.new[, 2]), ]
pg.add <- 0.5 * (pg.new + rbind(pg.new[-1, ], pg.new[1, ]))
end.points <- find.cut.z.pg(pg.add, pg0, center = center)
for (i in 1:nrow(pg.add)) {
tp <- cbind(pg.add[i, 1] + lam * (end.points[i, 1] - pg.add[i, 1]), pg.add[i, 2] + lam * (end.points[i, 2] - pg.add[i, 2]))
hd.tp <- find.hdepths.tp(tp, xy)
ind <- max(sum(hd.tp >= k), 1)
if (ind < length(hd.tp)) {
tp <- cbind(tp[ind, 1] + lam * (tp[ind + 1, 1] - tp[ind, 1]), tp[ind, 2] + lam * (tp[ind + 1, 2] - tp[ind, 2]))
hd.tp <- find.hdepths.tp(tp, xy)
ind <- max(sum(hd.tp >= k), 1)
}
pg.add[i, ] <- tp[ind, ]
}
pg.new <- rbind(pg.new, pg.add)
pg.new <- pg.new[chull(pg.new[, 1], pg.new[, 2]), ]
}
cut.p.sl.p.sl <- function(xy1, m1, xy2, m2) {
sx <- (xy2[2] - m2 * xy2[1] - xy1[2] + m1 * xy1[1])/(m1 - m2)
sy <- xy1[2] - m1 * xy1[1] + m1 * sx
if (!is.nan(sy)) return(c(sx, sy))
if (abs(m1) == Inf) return(c(xy1[1], xy2[2] + m2 * (xy1[1] - xy2[1])))
if (abs(m2) == Inf) return(c(xy2[1], xy1[2] + m1 * (xy2[1] - xy1[1])))
}
pos.to.pg <- function(z, pg, reverse = FALSE) {
if (reverse) {
int.no <- apply(outer(pg[, 1], z[, 1], ">="), 2, sum)
zy.on.pg <- pg[int.no, 2] + pg[int.no, 3] * (z[, 1] - pg[int.no, 1])
}
else {
int.no <- apply(outer(pg[, 1], z[, 1], "<="), 2, sum)
zy.on.pg <- pg[int.no, 2] + pg[int.no, 3] * (z[, 1] - pg[int.no, 1])
}
result <- ifelse(z[, 2] < zy.on.pg, "lower", "higher")
return(result)
if (all(result == "lower")) {
result <- ifelse(((z[, 2] - zy.on.pg)/max(z[, 2] - zy.on.pg) + 1e-10) < 0, "lower", "higher")
}
if (all(result == "higher")) {
result <- ifelse(((z[, 2] - zy.on.pg)/max(z[, 2] - zy.on.pg) - 1e-10) < 0, "lower", "higher")
}
return(result)
}
find.polygon.center <- function(xy) {
if (length(xy) == 2) return(xy[1:2])
if (nrow(xy) == 2) return(colMeans(xy))
n <- length(xy[, 1])
mxy <- colMeans(xy)
xy2 <- rbind(xy[-1, ], xy[1, ])
xy3 <- cbind(rep(mxy[1], n), mxy[2])
S <- (xy + xy2 + xy3)/3
F2 <- abs((xy[, 1] - xy3[, 1]) * (xy2[, 2] - xy3[, 2]) - (xy[, 2] - xy3[, 2]) * (xy2[, 1] - xy3[, 1]))
lambda <- F2/sum(F2)
SP <- colSums(cbind(S[, 1] * lambda, S[, 2] * lambda))
return(SP)
}
xydata <- if (missing(y)) x
else cbind(x, y)
if (is.data.frame(xydata)) xydata <- as.matrix(xydata)
if (any(is.na(xydata))) {
if (na.rm) {
xydata <- xydata[!apply(is.na(xydata), 1, any), , drop = FALSE]
warning("NA elements have been removed!!")
}
else {
xy.medians <- apply(xydata, 2, function(x) stats::median(x, na.rm = TRUE))
for (j in 1:ncol(xydata)) xydata[is.na(xydata[, j]), j] <- xy.medians[j]
warning("NA elements have been exchanged by median values!!")
}
}
if (length(xydata) < 4) {
stop("not enough data points")
return()
}
if ((length(xydata)%%2) == 1) {
stop("number of values isn't even")
return()
}
if (!is.matrix(xydata))
xydata <- matrix(xydata, ncol = 2, byrow = TRUE)
very.large.data.set <- nrow(xydata) > approx.limit
if (very.large.data.set) {
step <- (n <- nrow(xydata))/approx.limit
ind <- round(seq(1, n, by = step))
xy <- xydata[ind, ]
}
else xy <- xydata
n <- nrow(xy)
points.in.bag <- floor(n*aa)
prdata <- stats::prcomp(xydata)
is.one.dim <- (0 == max(prdata[[1]])) || (min(prdata[[1]])/max(prdata[[1]])) < 1e-05
if (is.one.dim) {
center <- colMeans(xydata)
res <- list(xy = xy, xydata = xydata, prdata = prdata, is.one.dim = is.one.dim, center = center)
class(res) <- "bagplot"
return(res)
}
if (nrow(xydata) <= 4) {
center <- colMeans(xydata)
res <- list(xy = xy, xydata = xydata, prdata = prdata, hdepths = rep(1, n), hdepth = rep(1, n), is.one.dim = is.one.dim,
center = center, hull.center = NULL, hull.bag = NULL, hull.loop = NULL, pxy.bag = NULL, pxy.outer = xydata,
pxy.outlier = NULL, exp.dk = xydata)
class(res) <- "bagplot"
return(res)
}
xym <- apply(xy, 2, mean)
xysd <- apply(xy, 2, stats::sd)
xyxy <- cbind((xy[, 1] - xym[1])/xysd[1], (xy[, 2] - xym[2])/xysd[2])
dx <- (outer(xy[, 1], xy[, 1], "-"))
dy <- (outer(xy[, 2], xy[, 2], "-"))
alpha <- atan2(y = dy, x = dx)
diag(alpha) <- 1000
for (j in 1:n) alpha[, j] <- sort(alpha[, j])
alpha <- alpha[-n, ]
m <- n - 1
hdepth <- rep(0, n)
dpi <- 2 * pi - 1e-06
mypi <- pi - 1e-06
minusplus <- c(rep(-1, m), rep(1, m))
if (FALSE) {
for (j in 1:n) {
a <- alpha[, j] + pi
h <- a < 10
a <- a[h]
init <- sum(a < mypi)
a.shift <- (a + pi)%%dpi
minusplus <- c(rep(-1, length(a)), rep(1, length(a)))
h <- cumsum(minusplus[order(c(a, a.shift))])
hdepth[j] <- init + min(h) + 1
}
}
find.hdepths <- function(xy, number.of.directions = 181) {
xy <- as.matrix(xy)
for (j in 1:2) {
xy[, j] <- xy[, j] - min(xy[, j])
if (0 < (h <- max(xy[, j]))) xy[, j] <- xy[, j]/max(xy[, j])
}
phi <- c(seq(0, 180, length = number.of.directions)[-1] * (2 * pi/360))
sinphi <- c(sin(phi), 1)
cosphi <- c(cos(phi), 0)
RM1 <- round(digits = 6, rbind(cosphi, sinphi))
hd <- rep(h <- length(xy[, 1]), h)
for (j in seq(along = sinphi)) {
xyt <- xy %*% RM1[, j]
hd <- pmin(hd, rank(xyt, ties.method = "min"), rank(-xyt, ties.method = "min"))
}
hd
}
hdepth <- find.hdepths(xy, 181 * precision)
hd.table <- table(sort(hdepth))
d.k <- cbind(dk = rev(cumsum(rev(hd.table))), k = as.numeric(names(hd.table)))
k.1 <- sum(points.in.bag < d.k[, 1])
k <- d.k[k.1, 2] + 1
center <- apply(xy[which(hdepth == max(hdepth)), , drop = FALSE], 2, mean)
hull.center <- NULL
if (3 < nrow(xy) && length(hd.table) > 0) {
n.p <- floor(1.5 * c(32, 16, 8)[1 + (n > 50) + (n > 200)] * precision)
h <- unique(sort(hdepth, decreasing = TRUE))
limit.hdepth.to.check <- sort(h)[min(length(h), 3)]
h <- cands <- xy[limit.hdepth.to.check <= hdepth, , drop = FALSE]
cands <- cands[chull(cands[, 1], cands[, 2]), ]
n.c <- nrow(cands)
if (is.null(n.c)) cands <- h
xyextr <- rbind(apply(cands, 2, min), apply(cands, 2, max))
if ((xyextr[2, 1] - xyextr[1, 1]) < 0.2 * (h <- diff(range(xy[, 1])))) {
xyextr[1:2, 1] <- mean(xyextr[, 1]) + c(-0.1, 0.1) * h
}
if ((xyextr[2, 2] - xyextr[1, 2]) < 0.2 * (h <- diff(range(xy[, 2])))) {
xyextr[1:2, 2] <- mean(xyextr[, 2]) + c(-0.1, 0.1) * h
}
h1 <- seq(xyextr[1, 1], xyextr[2, 1], length = n.p)
h2 <- seq(xyextr[1, 2], xyextr[2, 2], length = n.p)
tp <- cbind(as.vector(matrix(h1, n.p, n.p)), as.vector(matrix(h2, n.p, n.p, TRUE)))
tphdepth <- max(find.hdepths.tp(tp, xy))
tphdepth <- max(tphdepth, d.k[, 2])
num <- floor(2 * c(417, 351, 171, 85, 67, 43)[sum(n > c(1, 50, 100, 150, 200, 250))] * precision)
num.h <- floor(num/2)
angles <- seq(0, pi, length = num.h)
ang <- tan(pi/2 - angles)
kkk <- tphdepth
ia <- 1
a <- angles[ia]
xyt <- xyxy %*% c(cos(a), -sin(a))
xyto <- order(xyt)
ind.k <- xyto[kkk]
cutp <- c(xyxy[ind.k, 1], -10)
dxy <- diff(range(xyxy))
pg <- rbind(c(cutp[1], -dxy, Inf), c(cutp[1], dxy, NA))
ind.kk <- xyto[n + 1 - kkk]
cutpl <- c(xyxy[ind.kk, 1], 10)
pgl <- rbind(c(cutpl[1], dxy, -Inf), c(cutpl[1], -dxy, NA))
for (ia in seq(angles)[-1]) {
a <- angles[ia]
angtan <- ang[ia]
xyt <- xyxy %*% c(cos(a), -sin(a))
xyto <- order(xyt)
ind.k <- xyto[kkk]
ind.kk <- xyto[n + 1 - kkk]
pnew <- xyxy[ind.k, ]
pnewl <- xyxy[ind.kk, ]
if (abs(angtan) > 1e+10) {
pg.no <- sum(pg[, 1] < pnew[1])
if (0 < pg.no) {
cutp <- c(pnew[1], pg[pg.no, 2] + pg[pg.no, 3] * (pnew[1] - pg[pg.no, 1]))
pg <- rbind(pg[1:pg.no, ], c(cutp, angtan), c(cutp[1] + dxy, cutp[2] + angtan * dxy, NA))
}
else {
pg <- rbind(pg[1, ], c(pg[2, 1:2], NA))
}
pg.nol <- sum(pgl[, 1] >= pnewl[1])
if (0 < pg.nol) {
cutpl <- c(pnewl[1], pgl[pg.nol, 2] + pgl[pg.nol, 3] * (pnewl[1] - pgl[pg.nol, 1]))
pgl <- rbind(pgl[1:pg.nol, ], c(cutpl, angtan), c(cutpl[1] - dxy, cutpl[2] - angtan * dxy, NA))
}
else {
pgl <- rbind(pgl[1, ], c(pgl[2, 1:2], NA))
}
}
else {
pg.inter <- pg[, 2] - angtan * pg[, 1]
pnew.inter <- pnew[2] - angtan * pnew[1]
pg.no <- sum(pg.inter < pnew.inter)
if (is.na(pg[pg.no, 3])) pg[pg.no, 3] <- -Inf
cutp <- cut.p.sl.p.sl(pnew, ang[ia], pg[pg.no, 1:2], pg[pg.no, 3])
pg <- rbind(pg[1:pg.no, ], c(cutp, angtan), c(cutp[1] + dxy, cutp[2] + angtan * dxy, NA))
pg.interl <- pgl[, 2] - angtan * pgl[, 1]
pnew.interl <- pnewl[2] - angtan * pnewl[1]
pg.nol <- sum(pg.interl > pnew.interl)
if (is.na(pgl[pg.nol, 3])) pgl[pg.nol, 3] <- Inf
cutpl <- cut.p.sl.p.sl(pnewl, angtan, pgl[pg.nol, 1:2], pgl[pg.nol, 3])
pgl <- rbind(pgl[1:pg.nol, ], c(cutpl, angtan), c(cutpl[1] - dxy, cutpl[2] - angtan * dxy, NA))
}
}
if (2 < nrow(pg) && 2 < nrow(pgl)) {
limit <- 1e-10
idx <- c(TRUE, (abs(diff(pg[, 1])) > limit) | (abs(diff(pg[, 2])) > limit))
if (any(idx == FALSE)) {
pg <- pg[idx, ]
pg[, 3] <- c(diff(pg[, 2])/diff(pg[, 1]), NA)
}
idx <- c((abs(diff(pgl[, 1])) > limit) | (abs(diff(pgl[, 2])) > limit), TRUE)
if (any(idx == FALSE)) {
pgl <- pgl[idx, ]
pgl[, 3] <- c(diff(pgl[, 2])/diff(pgl[, 1]), NA)
}
pgl[, 2] <- pgl[, 2] - 1e-05
pg <- pg[-nrow(pg), ][-1, , drop = FALSE]
pgl <- pgl[-nrow(pgl), ][-1, , drop = FALSE]
indl <- pos.to.pg(round(pgl, digits = 10), round(pg, digits = 10))
indu <- pos.to.pg(round(pg, digits = 10), round(pgl, digits = 10), TRUE)
sr <- sl <- NULL
if (indu[(npg <- nrow(pg))] == "lower" & indl[1] == "higher") {
rnuml <- which(indl == "lower")[1] - 1
rnumu <- npg + 1 - which(rev(indu == "higher"))[1]
if (is.na(rnuml)) rnuml <- sum(pg[rnumu, 1] < pgl[, 1])
if (is.na(rnumu)) rnumu <- sum(pg[, 1] < pgl[rnuml, 1])
xyl <- pgl[rnuml, ]
xyu <- pg[rnumu, ]
sr <- cut.p.sl.p.sl(xyl[1:2], xyl[3], xyu[1:2], xyu[3])
}
if (indl[(npgl <- nrow(pgl))] == "higher" & indu[1] == "lower") {
lnuml <- npgl + 1 - which(rev(indl == "lower"))[1]
lnumu <- which(indu == "higher")[1] - 1
if (is.na(lnuml)) lnuml <- sum(pg[lnumu, 1] < pgl[, 1])
if (is.na(lnumu)) lnumu <- sum(pg[, 1] < pgl[lnuml, 1])
xyl <- pgl[lnuml, ]
xyu <- pg[lnumu, ]
sl <- cut.p.sl.p.sl(xyl[1:2], xyl[3], xyu[1:2], xyu[3])
}
pg <- rbind(pg[indu == "higher", 1:2, drop = FALSE], sr, pgl[indl == "lower", 1:2, drop = FALSE], sl)
if (!any(is.na(pg))) pg <- pg[chull(pg[, 1], pg[, 2]), ]
}
else {
if (2 < nrow(pgl)) { pg <- rbind(pg[2, 1:2], pgl[-c(1, length(pgl[, 1])), 1:2]) }
else { pg <- rbind(pg[-c(1, length(pg[, 1])), 1:2], pgl[2, 1:2]) }
}
hull.center <- cbind(pg[, 1] * xysd[1] + xym[1], pg[, 2] * xysd[2] + xym[2])
if (!any(is.na(hull.center))) center <- find.polygon.center(hull.center)
else hull.center <- rbind(center)
}
num <- floor(2 * c(417, 351, 171, 85, 67, 43)[sum(n > c(1, 50, 100, 150, 200, 250))] * precision)
num.h <- floor(num/2)
angles <- seq(0, pi, length = num.h)
ang <- tan(pi/2 - angles)
kkk <- k
if (kkk <= max(d.k[, 2])) {
ia <- 1
a <- angles[ia]
xyt <- xyxy %*% c(cos(a), -sin(a))
xyto <- order(xyt)
ind.k <- xyto[kkk]
cutp <- c(xyxy[ind.k, 1], -10)
dxy <- diff(range(xyxy))
pg <- rbind(c(cutp[1], -dxy, Inf), c(cutp[1], dxy, NA))
ind.kk <- xyto[n + 1 - kkk]
cutpl <- c(xyxy[ind.kk, 1], 10)
pgl <- rbind(c(cutpl[1], dxy, -Inf), c(cutpl[1], -dxy, NA))
for (ia in seq(angles)[-1]) {
a <- angles[ia]
angtan <- ang[ia]
xyt <- xyxy %*% c(cos(a), -sin(a))
xyto <- order(xyt)
ind.k <- xyto[kkk]
ind.kk <- xyto[n + 1 - kkk]
pnew <- xyxy[ind.k, ]
pnewl <- xyxy[ind.kk, ]
if (abs(angtan) > 1e+10) {
pg.no <- sum(pg[, 1] < pnew[1])
if (0 < pg.no) { cutp <- c(pnew[1], pg[pg.no, 2] + pg[pg.no, 3] * (pnew[1] - pg[pg.no, 1]))
pg <- rbind(pg[1:pg.no, ], c(cutp, angtan), c(cutp[1] + dxy, cutp[2] + angtan * dxy, NA))
}
else {
pg <- rbind(pg[1, ], c(pg[2, 1:2], NA))
}
pg.nol <- sum(pgl[, 1] >= pnewl[1])
if (0 < pg.nol) { cutpl <- c(pnewl[1], pgl[pg.nol, 2] + pgl[pg.nol, 3] * (pnewl[1] - pgl[pg.nol, 1]))
pgl <- rbind(pgl[1:pg.nol, ], c(cutpl, angtan), c(cutpl[1] - dxy, cutpl[2] - angtan * dxy, NA))
}
else {
pgl <- rbind(pgl[1, ], c(pgl[2, 1:2], NA))
}
}
else {
pg.inter <- pg[, 2] - angtan * pg[, 1]
pnew.inter <- pnew[2] - angtan * pnew[1]
pg.no <- sum(pg.inter < pnew.inter)
if (is.na(pg[pg.no, 3])) pg[pg.no, 3] <- -Inf
cutp <- cut.p.sl.p.sl(pnew, ang[ia], pg[pg.no, 1:2], pg[pg.no, 3])
pg <- rbind(pg[1:pg.no, ], c(cutp, angtan), c(cutp[1] + dxy, cutp[2] + angtan * dxy, NA))
pg.interl <- pgl[, 2] - angtan * pgl[, 1]
pnew.interl <- pnewl[2] - angtan * pnewl[1]
pg.nol <- sum(pg.interl > pnew.interl)
if (is.na(pgl[pg.nol, 3])) pgl[pg.nol, 3] <- Inf
cutpl <- cut.p.sl.p.sl(pnewl, angtan, pgl[pg.nol, 1:2], pgl[pg.nol, 3])
pgl <- rbind(pgl[1:pg.nol, ], c(cutpl, angtan), c(cutpl[1] - dxy, cutpl[2] - angtan * dxy, NA))
}
}
if (2 < nrow(pg) && 2 < nrow(pgl)) {
limit <- 1e-10
idx <- c(TRUE, (abs(diff(pg[, 1])) > limit) | (abs(diff(pg[, 2])) > limit))
if (any(idx == FALSE)) {
pg <- pg[idx, ]
pg[, 3] <- c(diff(pg[, 2])/diff(pg[, 1]), NA)
}
idx <- c((abs(diff(pgl[, 1])) > limit) | (abs(diff(pgl[, 2])) > limit), TRUE)
if (any(idx == FALSE)) {
pgl <- pgl[idx, ]
pgl[, 3] <- c(diff(pgl[, 2])/diff(pgl[, 1]), NA)
}
pgl[, 2] <- pgl[, 2] - 1e-05
pg <- pg[-nrow(pg), ][-1, , drop = FALSE]
pgl <- pgl[-nrow(pgl), ][-1, , drop = FALSE]
indl <- pos.to.pg(round(pgl, digits = 10), round(pg, digits = 10))
indu <- pos.to.pg(round(pg, digits = 10), round(pgl, digits = 10), TRUE)
sr <- sl <- NULL
if (indu[(npg <- nrow(pg))] == "lower" & indl[1] == "higher") {
rnuml <- which(indl == "lower")[1] - 1
rnumu <- npg + 1 - which(rev(indu == "higher"))[1]
if (is.na(rnuml)) rnuml <- sum(pg[rnumu, 1] < pgl[, 1])
if (is.na(rnumu)) rnumu <- sum(pg[, 1] < pgl[rnuml, 1])
xyl <- pgl[rnuml, ]
xyu <- pg[rnumu, ]
sr <- cut.p.sl.p.sl(xyl[1:2], xyl[3], xyu[1:2], xyu[3])
}
if (indl[(npgl <- nrow(pgl))] == "higher" & indu[1] == "lower") {
lnuml <- npgl + 1 - which(rev(indl == "lower"))[1]
lnumu <- which(indu == "higher")[1] - 1
if (is.na(lnuml)) lnuml <- sum(pg[lnumu, 1] < pgl[, 1])
if (is.na(lnumu)) lnumu <- sum(pg[, 1] < pgl[lnuml, 1])
xyl <- pgl[lnuml, ]
xyu <- pg[lnumu, ]
sl <- cut.p.sl.p.sl(xyl[1:2], xyl[3], xyu[1:2], xyu[3])
}
pg <- rbind(pg[indu == "higher", 1:2, drop = FALSE], sr, pgl[indl == "lower", 1:2, drop = FALSE], sl)
if (!any(is.na(pg))) pg <- pg[chull(pg[, 1], pg[, 2]), ]
}
else {
if (2 < nrow(pgl)) { pg <- rbind(pg[2, 1:2], pgl[-c(1, length(pgl[, 1])), 1:2]) }
else { pg <- rbind(pg[-c(1, length(pg[, 1])), 1:2], pgl[2, 1:2]) }
}
exp.dk <- cbind(pg[, 1] * xysd[1] + xym[1], pg[, 2] * xysd[2] + xym[2])
}
else {
exp.dk <- NULL
}
if (1 < kkk) kkk <- kkk - 1
ia <- 1
a <- angles[ia]
xyt <- xyxy %*% c(cos(a), -sin(a))
xyto <- order(xyt)
ind.k <- xyto[kkk]
cutp <- c(xyxy[ind.k, 1], -10)
dxy <- diff(range(xyxy))
pg <- rbind(c(cutp[1], -dxy, Inf), c(cutp[1], dxy, NA))
ind.kk <- xyto[n + 1 - kkk]
cutpl <- c(xyxy[ind.kk, 1], 10)
pgl <- rbind(c(cutpl[1], dxy, -Inf), c(cutpl[1], -dxy, NA))
for (ia in seq(angles)[-1]) {
a <- angles[ia]
angtan <- ang[ia]
xyt <- xyxy %*% c(cos(a), -sin(a))
xyto <- order(xyt)
ind.k <- xyto[kkk]
ind.kk <- xyto[n + 1 - kkk]
pnew <- xyxy[ind.k, ]
pnewl <- xyxy[ind.kk, ]
if (abs(angtan) > 1e+10) {
pg.no <- sum(pg[, 1] < pnew[1])
if (0 < pg.no) { cutp <- c(pnew[1], pg[pg.no, 2] + pg[pg.no, 3] * (pnew[1] - pg[pg.no, 1]))
pg <- rbind(pg[1:pg.no, ], c(cutp, angtan), c(cutp[1] + dxy, cutp[2] + angtan * dxy, NA))
}
else {
pg <- rbind(pg[1, ], c(pg[2, 1:2], NA))
}
pg.nol <- sum(pgl[, 1] >= pnewl[1])
if (0 < pg.nol) { cutpl <- c(pnewl[1], pgl[pg.nol, 2] + pgl[pg.nol, 3] * (pnewl[1] - pgl[pg.nol, 1]))
pgl <- rbind(pgl[1:pg.nol, ], c(cutpl, angtan), c(cutpl[1] - dxy, cutpl[2] - angtan * dxy, NA))
}
else {
pgl <- rbind(pgl[1, ], c(pgl[2, 1:2], NA))
}
}
else {
pg.inter <- pg[, 2] - angtan * pg[, 1]
pnew.inter <- pnew[2] - angtan * pnew[1]
pg.no <- sum(pg.inter < pnew.inter)
if (is.na(pg[pg.no, 3])) pg[pg.no, 3] <- -Inf
cutp <- cut.p.sl.p.sl(pnew, ang[ia], pg[pg.no, 1:2], pg[pg.no, 3])
pg <- rbind(pg[1:pg.no, ], c(cutp, angtan), c(cutp[1] + dxy, cutp[2] + angtan * dxy, NA))
pg.interl <- pgl[, 2] - angtan * pgl[, 1]
pnew.interl <- pnewl[2] - angtan * pnewl[1]
pg.nol <- sum(pg.interl > pnew.interl)
if (is.na(pgl[pg.nol, 3])) pgl[pg.nol, 3] <- Inf
cutpl <- cut.p.sl.p.sl(pnewl, angtan, pgl[pg.nol, 1:2], pgl[pg.nol, 3])
pgl <- rbind(pgl[1:pg.nol, ], c(cutpl, angtan), c(cutpl[1] - dxy, cutpl[2] - angtan * dxy, NA))
}
}
if (2 < nrow(pg) && 2 < nrow(pgl)) {
limit <- 1e-10
idx <- c(TRUE, (abs(diff(pg[, 1])) > limit) | (abs(diff(pg[, 2])) > limit))
if (any(idx == FALSE)) {
pg <- pg[idx, ]
pg[, 3] <- c(diff(pg[, 2])/diff(pg[, 1]), NA)
}
idx <- c((abs(diff(pgl[, 1])) > limit) | (abs(diff(pgl[, 2])) > limit), TRUE)
if (any(idx == FALSE)) {
pgl <- pgl[idx, ]
pgl[, 3] <- c(diff(pgl[, 2])/diff(pgl[, 1]), NA)
}
pgl[, 2] <- pgl[, 2] - 1e-05
pg <- pg[-nrow(pg), ][-1, , drop = FALSE]
pgl <- pgl[-nrow(pgl), ][-1, , drop = FALSE]
indl <- pos.to.pg(round(pgl, digits = 10), round(pg, digits = 10))
indu <- pos.to.pg(round(pg, digits = 10), round(pgl, digits = 10), TRUE)
sr <- sl <- NULL
if (indu[(npg <- nrow(pg))] == "lower" & indl[1] == "higher") {
rnuml <- which(indl == "lower")[1] - 1
rnumu <- npg + 1 - which(rev(indu == "higher"))[1]
if (is.na(rnuml)) rnuml <- sum(pg[rnumu, 1] < pgl[, 1])
if (is.na(rnumu)) rnumu <- sum(pg[, 1] < pgl[rnuml, 1])
xyl <- pgl[rnuml, ]
xyu <- pg[rnumu, ]
sr <- cut.p.sl.p.sl(xyl[1:2], xyl[3], xyu[1:2], xyu[3])
}
if (indl[(npgl <- nrow(pgl))] == "higher" & indu[1] == "lower") {
lnuml <- npgl + 1 - which(rev(indl == "lower"))[1]
lnumu <- which(indu == "higher")[1] - 1
if (is.na(lnuml)) lnuml <- sum(pg[lnumu, 1] < pgl[, 1])
if (is.na(lnumu)) lnumu <- sum(pg[, 1] < pgl[lnuml, 1])
xyl <- pgl[lnuml, ]
xyu <- pg[lnumu, ]
sl <- cut.p.sl.p.sl(xyl[1:2], xyl[3], xyu[1:2], xyu[3])
}
pg <- rbind(pg[indu == "higher", 1:2, drop = FALSE], sr, pgl[indl == "lower", 1:2, drop = FALSE], sl)
if (!any(is.na(pg))) pg <- pg[chull(pg[, 1], pg[, 2]), ]
}
else {
if (2 < nrow(pgl)) { pg <- rbind(pg[2, 1:2], pgl[-c(1, length(pgl[, 1])), 1:2]) }
else { pg <- rbind(pg[-c(1, length(pg[, 1])), 1:2], pgl[2, 1:2]) }
}
exp.dk.1 <- cbind(pg[, 1] * xysd[1] + xym[1], pg[, 2] * xysd[2] + xym[2])
if (is.null(exp.dk)) exp.dk <- exp.dk.1
if (nrow(d.k) == k.1 || nrow(d.k) == 1) lambda <- 0
else {
ind <- sum(d.k[, 2] <= k.1)
ind <- k.1
ndk.1 <- d.k[ind, 1]
ndk <- d.k[ind + 1, 1]
lambda <- (n*aa - ndk)/(ndk.1 - ndk)
}
cut.on.pdk.1 <- find.cut.z.pg(exp.dk, exp.dk.1, center = center)
cut.on.pdk <- find.cut.z.pg(exp.dk.1, exp.dk, center = center)
h1 <- (1 - lambda) * exp.dk + lambda * cut.on.pdk.1
h2 <- (1 - lambda) * cut.on.pdk + lambda * exp.dk.1
h <- rbind(h1, h2)
h <- h[!is.nan(h[, 1]) & !is.nan(h[, 2]), ]
list (xy=h[chull(h[, 1], h[, 2]), ])
}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.