如何根据一些点绘制形状(椭圆或椭圆形)并计算其面积? [英] How to draw a shape (ellipse or oval) following some points and calculate its area?

查看:26
本文介绍了如何根据一些点绘制形状(椭圆或椭圆形)并计算其面积?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试绘制树木年轮并计算它们的面积.但是,我注意到实际上并非所有环都具有像圆一样的对称半径.我有 4 个半径的数据测量值,我想在每个收音机的每个点之后绘制环(或任何类似的形状),就像这个例子(这个图是用 PowerPoint 中的矢量手动完成的):

问题是,在 R 中,我发现只能使用 symbols() 函数中的 circles 选项绘制这些环,我得到了这张图:

使用这个 R 脚本:

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 位置data$x <- (data$d - data$c)/2 # x 位置data$z <- rowMeans(data[,1:4]) # 无线电长度符号(x = 数据$x,y = 数据$y,圆圈=数据$z,xlim = c(-10, 10)*1.5, ylim = c(-10, 10)*1.5, 英寸 = F, fg = "orange", lwd = 2)

我检查了一些带有绘制椭圆函数的包(elliplotellipseellipseplotcar、等),但我不喜欢它们的功能.我对使用这些包没有兴趣,相反我想写一个自己的代码.

我的想法是用我的四个半径的数据值绘制一个最符合圆环真实图形的形状,它可以是椭圆形、椭圆形等.

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

任何方向对我都非常有用.

解决方案

If A &B 在 y 轴上,C &D 在 x 轴上,椭圆的参数不难计算.我使用optim()来获取参数(注意:这个方法有微小的错误,比如2.439826e-12).

数据操作

 # 将所有数据转换为 xy 坐标并生成环因子图书馆(重塑2);图书馆(dplyr)数据 <- 数据.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) )数据 <- t(数据)colnames(data) <- LETTERS[1:ncol(data)] # ring-factordf <-melt(data, value.name = "x") # 改成长格式df$y <- df$x # 制作xy坐标df[df$Var1==a"|df$Var1==b",x"] <- 0df[df$Var1=="c"|df$Var1=="d", "y"] <- 0

计算中心坐标,ox &哦

center <- df %>% group_by(Var2) %>% summary(sum(x)/2, sum(y)/2) %>% as.data.frame()

椭圆参数的计算;半长轴和短轴,ra &RB

opt.f <- function(par, subset, center) { # 目标函数ox <- center[[1]] # par[1] 和 par[2] 是 ra 和 rboy <- 中心[[2]]x <- 子集$xy <- 子集$ysum(abs((x - ox)^2/par[1]^2 + (y - oy)^2/par[2]^2 - 1)) # 来自椭圆方程}lev <- 水平(df$Var2)## 搜索参数res <- sapply(1:length(lev), function(a)优化(c(1,1),opt.f,子集=子集(df,Var2 == lev [a]),center = center[a, 2:3], control = list(reltol = 1.0e-12)))res # 结果.您可以通过 res[,1etc] 获取详细信息.值不是 0,而是接近于 0

绘图功能(可能有些软件包有类似的功能)

radian <- 函数(度)度/180*piplot.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))如果(phi == 0){func(ra*cos(theta)+ox, rb*sin(theta)+oy, ...)} 别的 {x <- ra*cos(theta)y <- rb*sin(theta)phi <- 弧度(phi)余弦<- cos(phi)正弦<- sin(phi)函数(余弦*x-正弦*y+ox,正弦*x+余弦*y+oy,...)}}

plot(0, type=n", xlim=c(-10, 10), ylim =c(-10, 10), asp=1, xlab=x", ylab=y",轴 = F)轴(1,pos=0);轴(2,pos=0,las=2)点(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], 长度=300)区域 <- sapply(res[1,], function(a) pi * a[1] * a[2])

I am trying to plot rings of trees and calculate their areas. However, I have noticed that in reality not all rings have symmetric radii like a circle. I have data measurements of 4 radii, and I would like to plot rings (or any similar shape) following each point of every radio like this example (this figure was done manually with vectors in PowerPoint):

the problem is that in R I found only the possibility to plot these rings with the circles option from the symbols() function, and I got this graph:

using this R script:

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)

I have checked some packages with functions to draw ellipses (elliplot, ellipse, ellipseplot, car, etc), but I don't like their functions. I am not interested in use these packages, on the contrary I would like to write an own code.

My idea is to plot a shape which best meets the real figure of a ring with my data values of the four radii, it can be an ellipse, oval, etc.

With a circle I am using only data of one radio (in my example, the mean of all radii). With a ellipse would be better, because I can use at least two values, the major-axis (A+B), and the minor-axis (C+D). But would be great to draw a shape that use the values of four radii (A, B, C, D) or even more radii.

Here a guy drew a very nice superellipse using a R script, and another one drew some ellipses likes rings also in R.

However, I don't know how to use their methods to my specific problem.

If somebody have idea how to start drawing at least an ellipse in R would be nice. But would be great to know how to draw a shape (oval, ellipse, etc.) using the values of four radii and finally calculate their area.

I would appreciate very much your help or any direction to do that.

UPDATE:

Thanks @cuttlefish44 for your excellent answer, that was very useful to explain tree growth to my students. However, most tropical trees have very irregular shapes and now I am wondering to know if can I draw this other shape with an additional radio "E" and the radii axes at different positions like this scheme:

any direction would be very useful for me.

解决方案

If A & B are on y-axis and C & D are on x-axis, it isn't difficult to calculate the parameters of ellipses. I used optim() to get params (Note: this approach has tiny error, such as 2.439826e-12).

data manipulation

 # 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

calculation of center coordinates, ox & oy

center <- df %>% group_by(Var2) %>% summarize(sum(x)/2, sum(y)/2) %>% as.data.frame()

calculation of parameters of ellipse; semi-major and -minor axis, 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

function to plot (Probably some packages have similar one)

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, ...)
  }
}

draw

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])

这篇关于如何根据一些点绘制形状(椭圆或椭圆形)并计算其面积?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆