Как генерировать случайные фигуры заданной области. (Язык R).? - PullRequest
2 голосов
/ 01 февраля 2011

У меня такой вопрос ... Я работаю над некоторыми алгоритмами кластеризации. Для этого сначала я экспериментирую с двумерными фигурами.

Учитывая конкретную область, скажем, 500 кв. Единиц. Мне нужно генерировать случайные фигуры.для конкретной области

скажем, Rect, Square, Triangle из 500 кв. единиц ... и т. д. Любые предложения о том, как мне следует решить эту проблему .. Я использую язык R ..

Ответы [ 4 ]

6 голосов
/ 01 февраля 2011

Это довольно просто сделать для правильного многоугольника.

Площадь n-стороннего правильного многоугольника с описанной окружностью радиуса R равна

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

Следовательно, зная n и A, вы можете легко найти R

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

Таким образом, вы можете выбрать центр, пройти на расстоянии R и сгенерировать n точек с 2pi/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 голос
/ 01 февраля 2011

Случайный квадрат площадью 500 м ^ 2 легко - это квадрат боковой площади (500) м. Вы заботитесь о вращениях? Затем поверните его с помощью runif (x, 0,2 * pi). Вы заботитесь о его местонахождении? Добавьте смещение (x, y), вычисленное из runif или любого другого значения.

прямоугольник? Учитывая длину любой пары сторон, у вас есть только свобода выбора длины двух других. Как вы выбираете длину первой пары сторон? Ну, вы можете использовать runif () между некоторыми «разумными» ограничениями для вашего приложения. Вы можете использовать rnorm (), но это может дать вам отрицательную длину, так что, возможно, rnorm в квадрате. Затем, как только вы получите эту сторону, длина другой стороны будет 500 / л. Поверните, переведите и добавьте соль и перец по вкусу.

Для треугольников формула площади равна половине базового временного значения высоты. Так что сгенерируйте базовую длину - снова, runif, rnorm и т. Д. - и затем выберите другую точку, дающую необходимую высоту. Поворот и т. Д.

В общем, форма имеет ряд «степеней свободы», и ограничение области, которая должна быть зафиксирована, ограничит хотя бы одну из этих свобод [1], поэтому, если вы начнете строить форму со случайными числами, вы получите до точки, где вы должны ввести вычисленное значение.

[1] ровно один? Я не уверен - это не степени свободы в статистическом смысле ...

0 голосов
/ 02 февраля 2011

Я бы предложил кодировать случайное блуждание соседних крошечных квадратов, чтобы агрегация крошечных квадратов могла иметь произвольную форму с известной площадью.

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

0 голосов
/ 01 февраля 2011

Было бы очень сложно создать общий метод.Но вы можете написать пример для 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};
}
...