2011-02-01 2 views
2

Мой вопрос в том, что ... Я работаю над некоторыми алгоритмами кластеризации. Для этого сначала я экспериментирую с формами 2d.Как создать случайные фигуры с заданной областью. (R-язык).?

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

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

+0

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

ответ

6

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

Область п-сторонний правильного многоугольника, с описанной окружностью радиусом R является

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

Поэтому, зная Н и вы можете легко найти 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) 
    } 
+0

Я отредактировал код, так что он немного чище. Если у меня будет время, я опубликую решение для общей (не регулярной) выпуклой формы позже. – nico

-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}; 
} 
+0

Это будет довольно сложно перенести, так как это - в R ... – nico

+1

Сложно? Едва! В этом есть только три строки. – Spacedman

+0

@Spacedman: Я имел в виду идею использования классов, а не фактический код для треугольника. Если OP запрашивает R, то либо дайте R-код, либо псевдокод, а не C#. – nico

1

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

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

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

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

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

0

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

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

Смежные вопросы