如何在给定指定区域的情况下生成随机形状。(R语言)。

时间:2011-02-01 06:05:13

标签: r 2d shapes area

我的问题是这个..我正在研究一些聚类算法..首先我正在试验2d形状..

鉴于特定区域说500sq单位..我需要为特定区域生成随机形状

说一个500平方米的矩形,正方形,三角形......等等。关于我应该如何解决这个问题的任何建议..我正在使用R语言..

4 个答案:

答案 0 :(得分:6)

对常规多边形执行此操作非常简单。

具有半径为R的外接圆的n边正多边形的面积为

A = 1/2 nR^2 * sin((2pi)/n)

因此,知道n和A你就可以轻松找到R

R = sqrt((2*A)/(n*sin((2pi)/n))

所以,你可以选择中心,距离R并以2pi/n角度增量生成n个点。

在R:

regular.poly <- function(nSides, area)
    {
    # Find the radius of the circumscribed circle
    radius <- sqrt((2*area)/(nSides*sin((2*pi)/nSides)))

    # I assume the center is at (0;0) and the first point lies at (0; radius)
    points <- list(x=NULL, y=NULL)
    angles <- (2*pi)/nSides * 1:nSides

    points$x <- cos(angles) * radius
    points$y <- sin(angles) * radius

    return (points);
    }


# Some examples
par(mfrow=c(3,3))

for (i in 3:11)
    {
    p <- regular.poly(i, 100)
    plot(0, 0, "n", xlim=c(-10, 10), ylim=c(-10, 10), xlab="", ylab="", main=paste("n=", i))
    polygon(p)
    }

我们可以推断为通用的凸多边形。

凸多边形的区域可以是: A = 1/2 * [(x1*y2 + x2*y3 + ... + xn*y1) - (y1*x2 + y2*x3 + ... + yn*x1)]

我们如上所述生成多边形,但偏离正多边形的角度和半径。

然后我们缩放点以获得所需的区域。

convex.poly <- function(nSides, area)
    {
    # Find the radius of the circumscribed circle, and the angle of each point if this was a regular polygon
    radius <- sqrt((2*area)/(nSides*sin((2*pi)/nSides)))
    angle <- (2*pi)/nSides

    # Randomize the radii/angles
    radii <- rnorm(nSides, radius, radius/10)
    angles <- rnorm(nSides, angle, angle/10) * 1:nSides
    angles <- sort(angles)

    points <- list(x=NULL, y=NULL)
    points$x <- cos(angles) * radii
    points$y <- sin(angles) * radii

    # Find the area of the polygon
    m <- matrix(unlist(points), ncol=2)
    m <- rbind(m, m[1,])
    current.area <- 0.5 * (sum(m[1:nSides,1]*m[2:(nSides+1),2]) - sum(m[1:nSides,2]*m[2:(nSides+1),1]))

    points$x <- points$x * sqrt(area/current.area)
    points$y <- points$y * sqrt(area/current.area)

    return (points)
    }

答案 1 :(得分:1)

500平方公尺面积的随机平方很容易 - 它是一个方格(500)米的正方形。你关心轮换吗?然后用runif(x,0,2 * pi)旋转它。你关心它的位置吗?添加从runif或其他任何内容计算的(x,y)偏移量。

矩形?鉴于任何一对边的长度,您只能自由选择其他两边的长度。你如何选择第一对边的长度?好吧,您可能希望在应用程序的某些“明智”限制之间使用runif()。你可以使用rnorm(),但这可能会给你负长度,所以可能是rnorm-squared。然后,一旦你有那边,另一边长度是500 / L.旋转,翻译,加入盐和胡椒调味。

对于三角形,面积公式为半基础 - 高度。因此,生成一个基本长度 - 再次,runif,rnorm等等 - 然后选择另一个给出所需高度的点。旋转等

总的来说,一个形状有多个“自由度”,约束要修复的区域将至少限制其中一个自由[1],所以如果你开始用随机数建立一个形状,你会来到了你必须加入计算值的那一点。

[1]恰好一个?我不确定 - 这些在统计意义上不是自由度......

答案 2 :(得分:0)

我建议编码相邻小方块的随机游走,这样小方块的聚合可以是已知区域的任意形状。

http://en.wikipedia.org/wiki/File:Random_walk_in2D.png

答案 3 :(得分:-1)

制作通用方法非常困难。 但是你可以编写3,4,5个边对象的例子。 这是一个随机三角形的例子。(在C#中)

class Triangle
{
  double Angle1;
  double Angle2;
  //double angle3; 180 - angle1 - angle2;
  double Base;
}
Triangle randomTriangle(double area){
  //A = (base*hieght)/2.0;
  double angle1 = *random number < 180*;
  double angle2 = *random number < (180 - angle1)*;

  *use trig to get height in terms of angles and base*
  double base = (area*2.0)/height;

  return new Triangle(){Angle1 = angle1, Angle2 = angle2, Base = base};
}