2016-10-22 127 views
1

我想绘制树的环和计算它们的面积。但是,我已经注意到,实际上并非所有的环都具有圆对称的半径。我具有4个半径数据测量,并且我想绘制以下这样例如每无线电的每个点环(或任何类似的形状)(该图中,用在PowerPoint矢量手动完成):如何绘制一些形状(椭圆形或椭圆形)并计算其面积?

enter image description here

的问题是,在RI只发现了绘制这些环从symbols()功能circles选项的可能性,我得到这个图:使用该R脚本 enter image description here

data <- data.frame(
a = c(1,4,5,8, 10), 
b = c(1, 3,7,9, 10), 
c = c(2, 6, 8, 9 ,10), 
d = c(1, 3, 4, 7, 9)) 

data$y <- (data$a - data$b)/2 # y position 
data$x <- (data$d - data$c)/2 # x position 
data$z <- rowMeans(data[,1:4]) # radio length 

symbols(x = data$x, y = data$y, circles=data$z, 
     xlim = c(-10, 10)*1.5, ylim = c(-10, 10)*1.5, inches = F, fg = "orange", lwd = 2) 

我已经检查了一些带有椭圆功能的软件包(elliplot,ellipse,ellipseplot,car等),但我不喜欢它们的功能。我对使用这些软件包不感兴趣,相反,我想写一个自己的代码。

我的想法是画出最符合与四米半径的我的数据值的环实景图的形状,也可以是一个椭圆形,椭圆形等

由于我只使用一个圆一个无线电的数据(在我的例子中,是所有半径的平均值)。 使用椭圆会更好,因为我可以使用至少两个值,即主轴(A + B)和次轴(C + D)。但是绘制一个使用四个半径(A,B,C,D)或甚至更多半径的值的形状会很棒。

Here一个人使用R script画了一个非常漂亮的superellipse,另外一个吸引一些ellipses likes ringsin R

但是,我不知道如何使用他们的方法来解决我的具体问题。

如果有人有想法如何开始绘制至少在R中的椭圆将是很好的。但如果知道如何使用四个半径的值绘制一个形状(椭圆,椭圆等)并最终计算出它们的面积,那就太好了。

非常感谢您的帮助或任何方向。

UPDATE:

感谢@ cuttlefish44你的出色答卷,这是解释树木生长到我的学生非常有用的。然而,大多数热带树木具有非常不规则的形状,现在我想知道如果我能有额外的无线电“E”,在这样的方案不同的位置半径轴得出这样的其它形状:

irregular stem shape

任何方向对我来说都是非常有用的。

回答

1

如果A & B位于y轴上且C & D位于x轴上,计算椭圆参数并不困难。我用optim()得到params(注意:这种方法有微小的错误,比如2.439826e-12)。

数据操纵
# change all data into xy coordinates and make ring-factor 
library(reshape2); library(dplyr) 

data <- data.frame(
    a = c(1, 4, 5, 8, 10), 
    b = c(1, 3, 7, 9, 10) * -1, 
    c = c(2, 6, 8, 9, 10) * -1, 
    d = c(1, 3, 4, 7, 9)) 

data <- t(data) 
colnames(data) <- LETTERS[1:ncol(data)] # ring-factor 
df <- melt(data, value.name = "x")  # change into long-form 

df$y <- df$x        # make xy coordinates 
df[df$Var1=="a"|df$Var1=="b", "x"] <- 0 
df[df$Var1=="c"|df$Var1=="d", "y"] <- 0 
中心坐标的计算,牛& OY
center <- df %>% group_by(Var2) %>% summarize(sum(x)/2, sum(y)/2) %>% as.data.frame() 
的椭圆的参数;计算装置半长轴和-minor轴,RA & RB
opt.f <- function(par, subset, center) {  # target function 
    ox <- center[[1]]       # par[1] and par[2] are ra and rb 
    oy <- center[[2]] 
    x <- subset$x 
    y <- subset$y 
    sum(abs((x - ox)^2/par[1]^2 + (y - oy)^2/par[2]^2 - 1)) # from ellipse equation 
} 

lev <- levels(df$Var2) 

## search parameters 
res <- sapply(1:length(lev), function(a) 
    optim(c(1,1), opt.f, subset = subset(df, Var2 == lev[a]), 
     center = center[a, 2:3], control = list(reltol = 1.0e-12))) 

res # result. you can get detail by res[,1etc]. values are not 0 but much nearly 0 
功能绘制(也许有些包有类似的一个)
radian <- function(degree) degree/180*pi 
plot.ellipse <- function(ox, oy, ra, rb, phi=0, start=0, end=360, length=100, func=lines, ...) { 
    theta <- c(seq(radian(start), radian(end), length=length), radian(end)) 
    if (phi == 0) { 
    func(ra*cos(theta)+ox, rb*sin(theta)+oy, ...) 
    } else { 
    x <- ra*cos(theta) 
    y <- rb*sin(theta) 
    phi <- radian(phi) 
    cosine <- cos(phi) 
    sine <- sin(phi) 
    func(cosine*x-sine*y+ox, sine*x+cosine*y+oy, ...) 
    } 
} 
plot(0, type="n", xlim=c(-10, 10), ylim =c(-10, 10), asp=1, xlab="x", ylab="y", axes = F) 
axis(1, pos=0);axis(2, pos=0, las=2) 
points(df$x, df$y) 
for(a in 1:length(lev)) plot.ellipse(ox = center[a, 2], oy = center[a, 3], 
            ra = res[,a]$par[1], rb = res[,a]$par[2], length=300) 

area <- sapply(res[1,], function(a) pi * a[1] * a[2]) 

enter image description here

+0

感谢您的出色答卷。但是,我有一个新问题来绘制更多不规则的形状。我已经对我的帖子进行了更新,以解释我需要的内容。或者你认为创建一个新问题会更好吗? –