#' Define Break Points from Midpoints
#'
#' @param midpoints a vector of midpoints.
#' @param min value of the lowest break.
#' @param max value of the highest break.
#' @param margin value to be subtracted/added to
#'         the lowest and highest midpoints. \cr
#'         default margin = ( midpoints[2]-midpoints[1] )/2
#'
#' @details
#' Break values from midpoint values: \cr
#'  \code{brk[1]=midp[1] - margin}\cr
#'  \code{brk[2]=midp[1] + (midp[2]-midp[1])/2} \cr
#'  \code{brk[3]=midp[2] + (midp[3]-midp[2])/2} \cr
#'  \code{brk[length(midpoints)+1]=midp[length(midpoints)] + margin} \cr
#'  where \code{margin=(midp[2]-midp[1])/2}. \cr
#'  In general, the break point is located at the center of two midpoints:\cr
#'  \code{brk[k]=0.5*(midp[k-1]+midp[k])}
#'  \cr
#'
#' Midpoint values from break values: \cr
#'  \code{midp[1]=0.5*(brk[1]+brk[2])} or {midp[1]=min}\cr
#'  \code{midp[2]=0.5*(brk[2]+brk[3])} \cr
#'  \code{midp[3]=2*brk[3]-midp[2]} \cr
#'  \code{brk[length(brk)-1]=2*brk[length(brk)-1]-midp[length(brk)-2]} \cr
#' \cr
#' Note that midp[1] is treated separately and it is assumed that
#' the break point is located at the center of two midpoints.
#' \cr\cr
#' Try below to see how the obs on the border are classified. \cr
#'    \code{ xx <- c(1,2,3,4,5,6,7) } \cr
#'    \code{ brks <- c(0,2,4,6,8) } \cr
#'    \code{ cc1 <- cut(xx,brks) } \cr
#'    \code{ cc2 <- cut(xx,brks, right=FALSE) } \cr
#'    \code{ Print(xx,as.character(cc1),as.character(cc2)) }\cr
#'
#' @return
#' A vector of break points of length length(midpoints)+1.
#'
#' @examples
#' midp <- seq(0,5,length.out=11)
#' brk <- midp2brk( midp, margin=1 )
#' Print(midp,brk)
#'
#' midp <- seq(0,5,length.out=11)
#' brk <- midp2brk( midp, margin=1 )
#' Print(midp,brk)
#'
#' set.seed(1701)
#' x <- rnorm(100)+2.5
#'
#' # histogram by native hist
#' resh <- hist( x, breaks=brk )
#'
#' # histogram by native barplot
#' # freq <- resh$counts
#' # names(freq) <- midp
#' # barplot( freq, space=0 )
#' barplot( resh$count,names.arg=midp, space=0, xlab="X", col="white"
#'         , sub="top and bottom bars contain outliers." )
#'
#' # Below causes error because 'brk' does not span the range of 'x'.
#' # brk <- midp2brk( midp )
#' # resh <- hist( x, breaks=brk )
#'
#' @export
#'

midp2brk <- function( midpoints, min=NULL, max=NULL, margin=NULL ){
 # define breaks via midpoints
 # Shin-ichi Mayekawa
 # 201760719,20
 # bugfix: 20170917
 # roxgen details: 20170917,1109
 #

 npoint=length(midpoints)
 if( is.null(margin) ) margin=(midpoints[2]-midpoints[1])/2
 breaks=( midpoints + c( midpoints[2:npoint], midpoints[npoint]+2*margin ) )/2
 breaks=c( midpoints[1]-margin, breaks )
 if( !is.null(max) ) breaks[npoint+1]=max  ##
 if( !is.null(min) ) breaks[1]=min
 return( breaks )

} # midp2brk





#' Define Midpoints from Break Points
#'
#' @param brk a vector of break points.
#' @param min The value of the lowest midpoint.
#'    This has priority over margin.
#'
#' @details
#' Break values from midpoint values: \cr
#'  \code{brk[1]=midp[1] - margin}\cr
#'  \code{brk[2]=midp[1] + (midp[2]-midp[1])/2} \cr
#'  \code{brk[3]=midp[2] + (midp[3]-midp[2])/2} \cr
#'  \code{brk[length(midpoints)+1]=midp[length(midpoints)] + margin} \cr
#'  where \code{margin=(midp[2]-midp[1])/2}. \cr
#'  In general, the break point is located at the center of two midpoints:\cr
#'  \code{brk[k]=0.5*(midp[k-1]+midp[k])}
#'  \cr
#'
#' Midpoint values from break values: \cr
#'  \code{midp[1]=0.5*(brk[1]+brk[2])} or {midp[1]=min}\cr
#'  \code{midp[2]=0.5*(brk[2]+brk[3])} \cr
#'  \code{midp[3]=2*brk[3]-midp[2]} \cr
#'  \code{brk[length(brk)-1]=2*brk[length(brk)-1]-midp[length(brk)-2]} \cr
#' \cr
#' Note that midp[1] is treated separately and it is assumed that
#' the break point is located at the center of two midpoints.
#' \cr\cr
#' Try below to see how the obs on the border are classified. \cr
#'    \code{ xx <- c(1,2,3,4,5,6,7) } \cr
#'    \code{ brks <- c(0,2,4,6,8) } \cr
#'    \code{ cc1 <- cut(xx,brks) } \cr
#'    \code{ cc2 <- cut(xx,brks, right=FALSE) } \cr
#'    \code{ Print(xx,as.character(cc1),as.character(cc2)) }\cr
#'
#' @return
#' A vector of midpoints of length length(brk)-1.
#'
#' @examples
#' midp <- c(0,1,2,4,6,9,10,11)
#' brk <- midp2brk( midp )
#' Print( midp, brk, brk2midp(brk) )
#' brk[1] <- -4
#' Print( midp, brk, brk2midp(brk) )
#'
#' @export
#'

brk2midp <- function( brk, min=NULL ){
 # recover midpoints from break points
 # Shin-ichi Mayekawa
 # 20170309
 # roxgen details: 20170917,1109
 # treat midp[1] separately: 20171109
 #

 len=length(brk)-1
 midp=numeric(len)
 if( !is.null(min) ) midp[1]=min
 else midp[1]=0.5*(brk[1]+brk[2])

 midp[2]=0.5*(brk[2]+brk[3])
 for( i in 3:len ){
  midp[i]=2*brk[i]-midp[i-1]
 }

 return( midp )

} # end of brk2midp




#' Generate n Equally Spaced Midpoints in [min,max]
#'
#' @param min The minimum value.
#' @param max Them maximum value.
#' @param n # of midpoints including min and max
#'
#' @details
#' \code{gen_midp( min, max, n )} is equivalent to 
#' \code{seq( min, max, len=n )}.
#'
#' @return A vector of length n.
#'
#' @examples
#' gen_midp( 0, 10, 6 )
#' gen_midp( 1, 11, 6 )
#' gen_midp( 0, 100, 11 )
#' gen_midp( 0, 100, 11 )
#'
#' @export
#'

gen_midp <- function( min, max, n ){
 # generate n equally spaced midpoints between [min,max]
 # Shin-ichi Mayekawa
 # 20170414
 #
 # Old sas/iml domain module.
 #
 return( ((max-min)/(n-1))*(0:(n-1)) + min )

} # end of gen_midp



