Nothing
#' Create data frame of x and y intervals of selected polygon segments
#' @param rule logic vector indicating which polygon segments are selected
#' @param cut_poly data.frame of a polygon
#' @author Liudas Daumantas
#' @noRd
.create_ints <- function(rule,cut_poly){
IDs <- which(rule)
data.frame(x1 = cut_poly[IDs,1],
y1 = cut_poly[IDs,2],
x2 = cut_poly[IDs+1,1],
y2 = cut_poly[IDs+1,2])
}
#' Indicate whether the provided polygon is above zero
#' @param lowest_up_intervals data frame of filtered polygon segments are the
#' nearest to the y axis.
#' @param polygon data frame of a polygon
#' @author Liudas Daumantas
#' @noRd
.is_pol_up <- function(lowest_up_intervals,polygon) {
.point.in.polygon(point.x = lowest_up_intervals[2,1],
point.y = lowest_up_intervals[2,2]-lowest_up_intervals[2,2]/2,
pol.x = polygon[,1],
pol.y = polygon[,2]) != 0
}
#' Convert polygon segments data.frame into points data.frame
#' @param inters data frame of x and y intervals of polygon segments
#' @noRd
.ints_to_pnts <- function(inters) {
idx<-cbind(rep(1:nrow(inters),each=2),rep(c(1,3),nrow(inters)))
idy<-cbind(rep(1:nrow(inters),each=2),rep(c(2,4),nrow(inters)))
pol <- round(data.frame(x=inters[idx],y=inters[idy]),6)
if (any(duplicated(pol))) {
pol <- pol[-which(duplicated(pol)),]
}
if (pol[1,2] != 0){
pol <- rbind(data.frame(x=0,y=0),pol)
}
if (pol[nrow(pol),2] != 0) {
pol <- rbind(pol,data.frame(x=pol$x[nrow(pol)],y=0))
}
return(pol)
}
#' Insert given rows to a given data frame at given locations
#' @param df data frame object where rows will be inserted
#' @param newrows data frame of rows to be inserted
#' @param r numeric vector of indeces that show where the rows should be placed
#' @author Liudas Daumantas
#' @noRd
.insert_filter_Rows <- function(df, newrows, r) {
df <- rbind(df,newrows)
df <- df[order(c(1:(nrow(df)-nrow(newrows)),r+0.5)),]
x3 <- dynGet(
x = "x3",
ifnotfound = stop("`x3` was not found in the calling environment.", call. = FALSE),
minframe = 1,
inherits = TRUE
)
if (x3 == 0) {
df <- df[df$x >= 0, ]
} else {
df <- df[df$x <= x3, ]
}
row.names(df) <- 1:nrow(df)
return(df)
}
#' Instead of indicated polygon vertexes, add new vertexes
#' with interpolated y coordinates
#'
#' @description Function removes indicated polygon vertexes. Instead of the
#' removed vertexes it adds new vertexes at provided x coordinates
#' for each mismatching pair of adjacent indicators of removal.
#' @param changes_log logical indicator, showing which vertexes are to be
#' removed from the polygon. Adjacent mismatches (TRUE FALSE and FALSE TRUE)
#' indicate where in the modified polygon vertexes should be added.
#' @param x3 an x coordinate at which y coordinates will be interpolated for
#' added vertexes.
#' @param polygon A data frame containing coordinates of a polygon vertexes.
#' @return A data frame containing coordinates of vertexes of a modified
#' polygon
#' @author Liudas Daumantas
#' @noRd
.find_y <- function(changes_log,x3,polygon){
change_id0 <- which( changes_log[ -1 ] - changes_log[ -length(polygon$x) ]
!=0 )
if (change_id0[1] == 1 & changes_log[1] ) {
change_id0 <- change_id0[-1]
} else {
if (change_id0[ length(change_id0) ] == length(polygon$x) - 1 &
changes_log[length(polygon$x) ] ) {
change_id0 <- change_id0[ -length(change_id0) ]
}
}
new_pts <- data.frame(x = rep(x3, length(change_id0)),
y = .pt_on_line(x1 = polygon$x[change_id0],
x2 = polygon$x[ change_id0 + 1 ],
y1 = polygon$y[change_id0],
y2 = polygon$y[ change_id0 + 1 ],
x3 = rep(x3,length(change_id0)) )
)
return( .insert_filter_Rows(polygon, new_pts, change_id0) )
}
#' Remove parts of a polygon that are outside of x range
#' of a split line
#'
#' @description Function removes polygon vortexes that are outside of x range
#' of a split line, as well as interpolates and adds vertexes where polygon
#' segments from deleted vertexes enters the allowed x range.
#' @param polygon A data frame containing coordinates of a polygon vertexes, an
#' output of .split_poly function that is rotated so that the split line is
#' horizontal, starting at x=0, y=0 and ending at some positive x, y = 0.
#' The provided polygon can be either closed or open.
#' @return A data frame containing the coordinates of vertexes of a provided
#' polygon that are inside an x range of a split line.
#' @author Liudas Daumantas
#' @noRd
.cut_by_x_margins <- function(polygon) {
# XXXX atein uzdaras polygonas- galima atverti iskart nestestavus
if (all(polygon[1,]==polygon[nrow(polygon),])){
polygon <- polygon[-nrow(polygon),]
}
pol1 <- .find_y(polygon$x <= 0, x3= 0,polygon)
return (.find_y(pol1$x >= pol1$x[ length(pol1$x) ],
x3 = pol1$x[ length(pol1$x) ], pol1) )
}
#' Filter segments of a polygon that are not OK (out of allowed y range,
#' turns left or are not the nearest to the Y axis)
#'
#' @param intervals a data frame of x and y intervals of a polygon segments.
#' These segments are pre-filtered by the allowed x ranges.
#' @return A data frame containing coordinates of vertexes of a modified
#' polygon
#' @author Liudas Daumantas
#' @noRd
.segment_filter <- function(intervals) {
if (nrow(intervals)>1){
intervals <- round(intervals,6)
# XXXX CHeezz Liudai! @.@ :O... intervals[,c(1,3)] is enough for range | ARBA NE, JEI SVARBU, KAD BUTU MAZENIS KAIREJE
int_x_ranges <- cbind(t(apply(intervals[,c(1,3)],1,range)),1:nrow(intervals))
# kaip su tom nelygybem lygybem? Po @.@ atrodo gerai pirmos dvi salygos,
# nes intervalai lyg ir turi buti su tais paciais endpointas,
# tai kai kurie endpointai logiska, kad sutampa, bet abieju pradzios
# negali sutapti (int_x_ranges pirmas stulpelis mazesnieji),
# kaip ir abieju pabaigos.
# Tuo tarpu trecia salyga atrodo pertekline, nes neisivaizduoju, kur imanoma
# kad vienos atkarpos pirmas endpointas butu kairiau kitos ir tuo paciu jos
# antras endpointas butu desiniau kitos. Tai tarsi diktuoja, kad endpointai
# nesiliecia. Tas gali butu imanoma tik tada, jei intervalai butu prafiltruoti.
# Ir taip, jie filtruoti su create_ints() ir is_x_shifted(), bet tai
# nufiltruoja tik tas vietas, kur x nesikeicia
# Taigi, endopointai turetu visur tureti bent viena lygybe. Tikrinu: Gavosi butent taip.
# Taip pat, reikalinga butu ir kita salyga, jei trecia yra reikalinga -
# kur viena o atkarpa butu praryta, o ne apziotu kaip numato dabar paskutine
# salyga. Taip trecia reikalinga ir reikalinga butent tais atvejais, kai
# persidengia negretimos atkarpos. TY. persidengti gali artimos atkarpos, jei
# suka linija ten is kur atejo, bet gali ir toliau uzklisti.
# Ketvirta salyga kazkodel pertekline.... Pasirodo gal ir viskas buvo gerai :-(
# ISVADA: palieku kol kas papildoma salyga, veliau reiks su ja ir be jos padaryt
# ir pazet ar ji reikalinga, ar ne. NES - be trecios neveikia, o ketvirta neitakoja
# sio atvejo. Taigi, trecia ir ketvirta neanalogiska, tik nera atveju ketvirtos
overlap_log <- apply(int_x_ranges[,1:2], 1,function(o) {
(o[1] >= int_x_ranges[,1] & o[1] < int_x_ranges[,2] ) |
( o[2] > int_x_ranges[,1] & o[2] <= int_x_ranges[,2] ) |
(o[1] <= int_x_ranges[,1] & o[2] >= int_x_ranges[,2]) |
(o[1] >= int_x_ranges[,1] & o[2] <= int_x_ranges[,2])
})
diag(overlap_log) <- FALSE
# stulpeliai atitinka obs. (eilutes int_x_ranges). eilutes - su kuo persidengia siu obs eilutes
# noverlap_int_log - indikatoriai intervalu, kurie nepersidengia su niekuo
# overlap_int_ranges - intervalai, kurie persidengia su kitais intervalais
noverlap_int_log <- apply(!overlap_log,2,all)
if (any(noverlap_int_log)) {
overlap_int_ranges <- int_x_ranges[-which(noverlap_int_log),]
} else {
overlap_int_ranges <- int_x_ranges
}
# Jei nera persidengianciu intervalu, grazinam nekoreguotus intervalus atitransformuotus i taskus
if (nrow(overlap_int_ranges)==0) {
return(.ints_to_pnts(intervals))
}
# Isruosiuoti intervalu endpoitai, be duplikatu (taskai isilgai x)
x_end_points <- sort(unique(c(overlap_int_ranges[,1:2])))
# intervalai isrusiuoti x didejimo tvarka,o ne taip kaip poligonas nupaisytas
x_ranges <- cbind(x_end_points[-length(x_end_points)],x_end_points[-1])
# is end_points sukurtuose x_ranges gali buti intervalai, kur persidengimo
# su overlap_int_ranges nera
# TOKIU INTERVALO ISMETIMO KODAS (letesnis sprendimas, patestavus):
#id_interval_gap <- which((overlap_int_ranges[-1,3] - overlap_int_ranges[-nrow(overlap_int_ranges),3]) != 1)
#if (length(id_interval_gap)>0){
# imanoma, kad overlap_int_ranges gapinis intervalas nera butinai mazesnio x. x_ranges isrusiuotas, overlap_int_ranges ne
# id_interval_gap + 1
# PROBLEMA: gali gautis ir taip, kad x_ranges intervalai isrusiuoti
# visai nebera salia tie, kurie buvo salia su overlap_int_ranges ir ties
# rastu luziu, pvz. veliau ar pries poligono atkarpai patekus i ta gapini
# intervala. tokiu atveju sprendimas butu, intervalus ismetines is x_ranges
# pagal x_ranges_int_id rezultata (jei sarasas - randi tuscius id ir
# istrini atitinkamus x_ranges, tada kartoji x_ranges_int_id)
# Taciau kita vertus, tas gapinis intervalas atsiranda del to, kad
# tame intervale nera persidengianciu intervalu, tai gal ir negali isiterpti
# niekas i ji
# gali buti daugiau nei vienas id_del
#gap_del <- data.frame(x1 = numeric(length(id_interval_gap)),
# x2 = numeric(length(id_interval_gap)))
#for (i in 1:length(id_interval_gap)){
# if (overlap_int_ranges[id_interval_gap[i],2] <
# overlap_int_ranges[id_interval_gap[i]+1,1]){
# gap_del[i,] <- c(overlap_int_ranges[id_interval_gap[i],2],
# overlap_int_ranges[id_interval_gap[i]+1,1])
# } else {
#gap_del[i,] <- c(overlap_int_ranges[id_interval_gap[i]+1,2],
# overlap_int_ranges[id_interval_gap[i],1])
#}
# x_ranges <- x_ranges[-(which(x_ranges[,1] == gap_del[i,1] &
# x_ranges[,2] == gap_del[i,2])),]
# }
# }
x_ranges_int_id <- apply(x_ranges, 1,function(o) {
# su kuriais poligono nerusiuotais persidengianciais intervalais, persidengia
# kiekvienas rusiuotas persidengiantis intervalas (o arba x_ranges obs, eilute)
# su savimi paciu aisku ir plius gal dar kazkas dar (nes intervalai,
# kurie tik su savimi persidengia nufiltruoti --> diag(overlap_log) <- FALSE,
# taciau overlap_int_ranges isdalies persidengiantys intervalai gali
# tureti x_ranges atkarpas, kurios nepersidengia su daugiau niekuo.
# Pastariosios gaunamos isrusiavus persidengianciu intervalu endpointus ir
# is ju padarius intervalus)
# cia vel galimai truksta dar ketvirtos salygos, kur o intervalas yra prarytas
# Iterpiu salyga, bet niekas nesikeicia. BUTINA BUS PRATIKRINTI
ids <- which(
(o[1] >= overlap_int_ranges[,1] & o[1] < overlap_int_ranges[,2] ) |
(o[2] > overlap_int_ranges[,1] & o[2] <= overlap_int_ranges[,2] ) |
(o[1] <= overlap_int_ranges[,1] & o[2] >= overlap_int_ranges[,2]) |
(o[1] >= overlap_int_ranges[,1] & o[2] <= overlap_int_ranges[,2]))
# is visu su o intervalu persidengianciu nerusiuotu intervalu
# atrenkam ID to nerusiuoto intervalo, kurio y, o intervalo (su kuriuo
# persidengia) viduryje yra arciausiai nulio. Taigi, gaunam
# overlap_int_ranges id, kurie yra prarusiuoti ir kuriu Y galima naudoti
# x_ranges intervalams priskirti
overlap_int_ranges[ids[which.min(abs(.pt_on_line(
x1 = intervals$x1[overlap_int_ranges[ids,3]],
x2 = intervals$x2[overlap_int_ranges[ids,3]],
y1 = intervals$y1[overlap_int_ranges[ids,3]],
y2 = intervals$y2[overlap_int_ranges[ids,3]],
x3 = rep(o[1]+(o[2]-o[1])/2,length(ids)))))],3]
})
if (is.list(x_ranges_int_id)) { # then this side should not be the one
# needed. Could be improved by returning indicator and moving on to
# the next side. If both sides gets indicator, then abort
x_ranges<- x_ranges[-which(unlist(lapply(x_ranges_int_id, function(o)
{length(o)<1}))),]
x_ranges_int_id <- apply(x_ranges, 1,function(o) {
# su kuriais poligono nerusiuotais persidengianciais intervalais, persidengia
# kiekvienas rusiuotas persidengiantis intervalas (o arba x_ranges obs, eilute)
# su savimi paciu aisku ir plius gal dar kazkas dar (nes intervalai,
# kurie tik su savimi persidengia nufiltruoti --> diag(overlap_log) <- FALSE,
# taciau overlap_int_ranges isdalies persidengiantys intervalai gali
# tureti x_ranges atkarpas, kurios nepersidengia su daugiau niekuo.
# Pastariosios gaunamos isrusiavus persidengianciu intervalu endpointus ir
# is ju padarius intervalus)
# cia vel galimai truksta dar ketvirtos salygos, kur o intervalas yra prarytas
# Iterpiu salyga, bet niekas nesikeicia. BUTINA BUS PRATIKRINTI
ids <- which(
(o[1] >= overlap_int_ranges[,1] & o[1] < overlap_int_ranges[,2] ) |
(o[2] > overlap_int_ranges[,1] & o[2] <= overlap_int_ranges[,2] ) |
(o[1] <= overlap_int_ranges[,1] & o[2] >= overlap_int_ranges[,2]) |
(o[1] >= overlap_int_ranges[,1] & o[2] <= overlap_int_ranges[,2]))
# is visu su o intervalu persidengianciu nerusiuotu intervalu
# atrenkam ID to nerusiuoto intervalo, kurio y, o intervalo (su kuriuo
# persidengia) viduryje yra arciausiai nulio. Taigi, gaunam
# overlap_int_ranges id, kurie yra prarusiuoti ir kuriu Y galima naudoti
# x_ranges intervalams priskirti
overlap_int_ranges[ids[which.min(abs(.pt_on_line(
x1 = intervals$x1[overlap_int_ranges[ids,3]],
x2 = intervals$x2[overlap_int_ranges[ids,3]],
y1 = intervals$y1[overlap_int_ranges[ids,3]],
y2 = intervals$y2[overlap_int_ranges[ids,3]],
x3 = rep(o[1]+(o[2]-o[1])/2,length(ids)))))],3]
})
}
inters <- data.frame(x1 = x_ranges[,1],y1 = .pt_on_line(
x1 = intervals[x_ranges_int_id,1],
x2 = intervals[x_ranges_int_id,3],
y1 = intervals[x_ranges_int_id,2],
y2 = intervals[x_ranges_int_id,4],
x3 = x_ranges[,1]), x2 = x_ranges[,2],
y2 = .pt_on_line(
x1 = intervals[x_ranges_int_id,1],
x2 = intervals[x_ranges_int_id,3],
y1 = intervals[x_ranges_int_id,2],
y2 = intervals[x_ranges_int_id,4],
x3 = x_ranges[,2]))
if (any(noverlap_int_log)) {
# turim x_ranges x intervalus, kurie tvarkingai isrusiuoti. Kiekvienam
# tokiam intervalui, zimone kuria poligono atkarpa naudoti
# (turim x_ranges_int_id)
#
# suklijuojam x_ranges_int_id ( overlap_int_ranges pateiktus teisinga eiles
# tvarka kiekvienam x_ranges) su intervalais, kurie su niekuo nepersidenge
# PASTARIEJI NERUSIUOTI, NETVARKINGI
#
# MANO SIULYMAS: X_RANGES X INTERVALAMS SUGENERUOTI Y VERTES IR GAUTI
# GERAI RUSIUOTAS ATKARPAS PERSIDENGIMU SRITYJE
# TADA SUJUNGI SU ATKARPOMIS, KURIOS NEOVERLAPINA, IR NUKREIPTOS I DESINE
# GALIAUSIAI ISRUSIUOTI PAGAL INTERVALU PRADZIAS.
# ARBA JEI DARYT PANASIAI KAIP BUVO, TAI:
# GAUNAM NEOVERLAPINANCIU INTERVALU x_RANGES
#
inters_nover <- t(apply(intervals[which(noverlap_int_log),],1,function(o){
id <- which.min(c(o[1],o[3]))
if (id == 1 ) o else o[c(3,4,1,2)]
}))
inters <- rbind(inters,inters_nover)
id_ord <- order(inters[,1])
inters <- inters[id_ord,]
# x_ranges_int_id <- c(x_ranges_int_id,which(noverlap_int_log))
# grazina tvarka intervalu, kuri isrusiuota pagal intervalu pradzias.
# Jei intervalai nepersidengiantys tai turetu issirusiuoti taip, kad
# gretimu atkarpu x intervalai sugultu salia, einant is kaires i desine.
#
# ID PERRUSIUOJAMI PAGAL poligono atkarpu kairinius taskus
# x_ranges_int_id_order <- order(sapply(x_ranges_int_id,
# function(o){
# min(intervals[
# o,c(1,3)])}))
# naudojant gauta tvarka, persusiuojami intervalu indeksai
# gaunam rusiavimo indeksus skirtus perrusiuoti intervalus
#
# x_ranges_int_id <- x_ranges_int_id[x_ranges_int_id_order]
# x_ranges sudedamas su analogiskos strukturos nepersidengianciais
# intervalais ir isrusiuojami pagal x_ranges_int_id_order tvarka
# nesuprantu, kodel tik.
#x_ranges <- rbind(x_ranges,t(apply(intervals[which(noverlap_int_log),
# c(1,3)]
# ,1,range)))[x_ranges_int_id_order,]
}
# apsukam intervalus (cia kaip ir aisku) (galiMAI NEBUTINAS VEIKSMAS)
# intervals_selected <- t(apply(intervals[x_ranges_int_id,],1,
# function(o){
# id <- which.min(c(o[1],o[3]))
# if (id == 1 ) o else o[c(3,4,1,2)]
# }))
#intervals_selected <- intervals_selected[paste(x_ranges_int_id),]
# kiekienam x intervalui, paimam atrinkta intervala poligono ir panaudojam
# sugeneruoti taskus
# inters <- data.frame(x1 = x_ranges[,1],y1 = .pt_on_line(
# x1 = intervals_selected[,1],
# x2 = intervals_selected[,3],
# y1 = intervals_selected[,2],
# y2 = intervals_selected[,4],
# x3 = x_ranges[,1]), x2 = x_ranges[,2],
# y2 = .pt_on_line(
# x1 = intervals_selected[,1],
# x2 = intervals_selected[,3],
# y1 = intervals_selected[,2],
# y2 = intervals_selected[,4],
# x3 = x_ranges[,2]))
} else{
inters <- intervals
}
in.pol <- .ints_to_pnts(inters)
return(in.pol)
}
#' Remove left-turning segments of a polygon divided with horizontal split line
#'
#' @description This function from a polygon derived with .split_poly
#' function extracts the maximum area part that is directly above or below
#' split line (depending on the which side of divided polygon is provided) and
#' that has no left-turning segments.
#' @param polygon A data frame containing coordinates of a polygon, output of
#' .split_poly function that is rotated so that the split line is horizontal,
#' starting at x=0, y0 and ending at some positive x, y = 0.
#' The provided polygon can be either closed or open.
#' @return A list of two values:
#' `[[1]]` A data frame containing the coordinates of the extracted polygon part.
#' The returned polygon is open and it is not strictly inside a provided
#' polygon, since it inherits vertical & right-turning segments that are
#' directly above or below the split line.
#' `[[2]]` -1 or +1 integer indicating the side of the extracted polygon in
#' relation to the split line (+1 above, -1 below)
#' @author Liudas Daumantas
#' @examples #Creating a data.frame of an irregular polygon
#' poly<-data.frame(x=c(0,-1,12,0,5,12,12,7,-5,
#' 11,-3,10,-10,-10,15,15,-1,13,13,-7,-7,0),
#' y=c(0,5,10,4,4,3,-3,-10,-11,-4,-4,0,-2,20,20,-20,-20,-15,15,15,2,0))
#' plot(poly,type='o',main='Horizontal Split Line')
#' #Horizontal Split Line
#' lines(poly[c(1,12),1],poly[c(1,12),2],lty='dotted')
#' #Dividing a polygon
#' upper_half <- split_poly(polygon = poly, split_ids = c(1,12), min_id = 1,
#' trivial_side = F, poli_side = T)
#' lower_half <- split_poly(polygon = poly, split_ids = c(1,12), min_id = 1,
#' trivial_side = F, poli_side = F)
#' lines(upper_half,col=4)
#' lines(lower_half,col=2)
#' #Filtering left turning segments
#' upper_half_lf <- .inner_poly_hull(upper_half)
#' lower_half_lf <- .inner_poly_hull(lower_half)
#' lines(upper_half_lf[[1]],col=4,lwd=3)
#' lines(lower_half_lf[[1]],col=2,lwd=3)
#' @noRd
.inner_poly_hull<-function(polygon){
if ( all(polygon[-1,1]-polygon[-nrow(polygon),1]>=0 ) ){
return(
list(polygon,sign(polygon[2,2]))
)
}
v_cutted_poly <- .cut_by_x_margins(polygon)
x_shift <- v_cutted_poly[,1][-1] -
v_cutted_poly[,1][-nrow(v_cutted_poly)]
if (all(x_shift>=0)){
if (!(all(v_cutted_poly$y <=0) | all(v_cutted_poly$y >=0))){
if(all(x_shift[1:2] == c(0,0))){
v_cutted_poly <- v_cutted_poly[-2,]
}
if(all(x_shift[(length(x_shift)-1):length(x_shift)] ==
c(0,0))){
v_cutted_poly <- v_cutted_poly[-(nrow(v_cutted_poly)-1),]
}
}
return(
list(v_cutted_poly,sign(v_cutted_poly[2,2]))
)
}
is_x_shift <- x_shift != 0
if (all(v_cutted_poly$y <=0) | all(v_cutted_poly$y >=0) ) {
side <- sign(v_cutted_poly$y[2])
int <- .create_ints(is_x_shift,v_cutted_poly)
return(
list(.segment_filter(int),side)
)
} else {
upper_int <- .create_ints(is_x_shift & v_cutted_poly[,2][-1] >=0 &
v_cutted_poly[,2][-nrow(v_cutted_poly)] >=0
,v_cutted_poly)
lowest.up.intervals <- .segment_filter(upper_int)
if (is.null(lowest.up.intervals)){
side <- FALSE
} else {
side <- .is_pol_up(lowest.up.intervals,polygon)
}
if (side) {
return(
list(lowest.up.intervals, 1)
)
} else {
lower_int <- .create_ints(is_x_shift & v_cutted_poly[,2][-1] <=0 &
v_cutted_poly[,2][-nrow(v_cutted_poly)] <=0,
v_cutted_poly)
return(
list(.segment_filter(lower_int),-1)
)
}
}
}
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.