1

各行が円の中心を指定する座標のベクトルがあります。

x <- runif(5,0,2)
y <- runif(5,0,2)

ご覧のとおり、円の中心はすべて正方形(0,2)内にあります。

各円の半径は0.2です。元の円の境界内で円の中心をランダムにシフトしたいと思います。私はこれができると思った:

radii  <- (sample(20,5,replace=TRUE))/100
angles <- sample(360,5,replace=TRUE)
newx <- x + radii*(cos(angles))
newy <- y + radii*(sin(angles))

ただし、これを行うと、技術的には正方形(0,2)の外側にある円の中心を取得できることに気付きました。newx負のnewy値を拒否するループを書いてみることができます。しかし、これを数万行にわたって実行する必要があり、これの速度について心配しています。ループに頼らずにこの条件付き座標シフトを実行することは可能ですか?

私のルールセットは次のとおりです。

  1. センターごとに新しいサークルセンターを選択します。

  2. 新しい中心は、各円の領域内にある必要があります(元の中心から半径0.2の距離)

  3. 新しいセンターは、元の正方形内にある必要があります。

  4. 中心が円の境界に接する場合、反射の法則に従って反射する必要があります(選択したランダム半径距離の残りの長さを反映します)

ここに画像の説明を入力してください

4

2 に答える 2

1

関数inpipinoutパッケージ splancs は非常に便利です。ポイントがポリゴン内にあるかどうかを確認するために使用できます。任意の多角形 (正方形など) を表す 2 列の行列が必要です。この関数は、C および Fortran プログラムを使用して高速化されています。

正方形の場合:

square <- cbind(c(0, 10, 10, 0), c(0, 0, 10, 10)) # In case side = 10

次に、すべての新しいセンターを作成します ( forとのrunif代わりに使用することをお勧めしますが、それはあなた次第です)。次に、それらの中心が 1 行の正方形の内側にあるかどうかを確認します。sampleradiiangle

inside <- inout(newCenters, square)
newCenters <- newCenters[inside]

その後、選択した場所を再作成するために必要なすべての手順をnewCenters、正方形の内側に収まるまで必要な回数実行する必要があります。whileこれにはループ (または同等のもの) が必要であることに注意してください。

同じパッケージ (splancs) にはcsr、ポリゴン内にランダムなポイントを作成するこの関数があることにも注意してください。したがって、原則として、正方形の外側にあるすべての円周の一部を切り取ってから、結果のポリゴン (切り取った円) をこの関数への入力として使用できます。lapplyすべてのカットサークルにループ (または多分) を使用する必要があるため、これは遅くなる可能性があります。

最後のアイデアとして、2 つの戦略を組み合わせることができるかもしれません。最初に、正方形の内側に完全に収まるすべての円周 (または、周囲から 2 以上の距離にあるすべての中心) に対して最初のアイデアを使用します。次にcsr、残りのすべての円に関数を使用します。

お役に立てれば!

于 2012-09-24T15:05:14.977 に答える
1

このようなもの:

#lets do only one point first
x <- runif(1,0,2)
y <- runif(1,0,2)


randomwalk <- function (pos) {
  x <- pos[1]
  y <- pos[2]
  radius  <- (sample(20,1,replace=TRUE))/100
  angle <- sample(360,1,replace=TRUE)
  newx <- x + radius*(cos(angle))
  newy <- y + radius*(sin(angle))

  if (newy > 2) { #check the geometric calculations
    r2 <- (2-y)/sin(angle)

    hitx <- x + r2*(cos(angle))
    hity <- 2

    newx <- hitx + (radius-r2)*sin(angle)
    newy <- hity - (radius-r2)*cos(angle)
  } 

  #implement other borders yourself
  #and include a check, which border is hit first
  #and include the possibility for multiple hits 
  #(e.g., left border and then top border)

  cbind(newx,newy)
}

resx <- vector(50,mode="numeric")
resy <- vector(50,mode="numeric")

res <- cbind(resx,resy)

res[1,] <- cbind(x,y)


for (i in 2:50) {
  res[i,] <- randomwalk(res[i-1,])
}

これにはまだいくつかの幾何学的エラーが含まれていると思われますが、確認する時間がありません。

于 2012-09-24T13:21:15.957 に答える