円柱と円錐に (別々に) ランダムかつ一様に点を生成したいと考えています。円柱は、その中心、半径、および高さによって定義されます。コーンも同仕様。各形状の境界ボックスを取得できるので、境界ボックス内にポイントを生成することを考えていました。ただし、それらをシリンダー/コーンに投影する方法、またはこれが最善のアイデアであるかどうかはわかりません。
助言がありますか?
ありがとう。
円柱と円錐に (別々に) ランダムかつ一様に点を生成したいと考えています。円柱は、その中心、半径、および高さによって定義されます。コーンも同仕様。各形状の境界ボックスを取得できるので、境界ボックス内にポイントを生成することを考えていました。ただし、それらをシリンダー/コーンに投影する方法、またはこれが最善のアイデアであるかどうかはわかりません。
助言がありますか?
ありがとう。
シリンダーケースは微妙です。半径 r > 0、高さ h > 0 の円柱が (x, y, z) = (r cos φ, r sin φ, z) のイメージである場合、φ ∈ [0, 2π[ および z ∈ [-h /2, h/2] の場合、これらの間隔で φ と z をランダムに選択するだけです。もちろん、標準のパラメータ化を使用して円錐を単純にパラメータ化することもできますが、その場合、面積要素はパラメータ平面上で一定にならないため、ポイントの分布はランダムになりません。したがって、別のパラメータ化を見つける必要があります。このトピックについては、私の AlgoSim サイトで球体について詳しく説明しました。
これを考える1つの方法は、円柱と円錐の両方を平らな面に開梱できることです。それぞれを上から下に直線で切るだけです。
円柱は長方形に展開されます(上部と下部を含める場合は、ディスクを2つ追加します)。
円錐は、円の弧である湾曲した底を持つ三角形に展開します(円錐の底を含める場合は、ディスクを追加します)。
R
これらの平らな面をxy平面上の長方形の中に埋め込むのは簡単です。で均一に分散されたポイントを生成しR
、それらが平面の内側にあるときはいつでも、元のサーフェスにマップし直します。
角度と高さの観点から円錐を調整しようとする他のいくつかの答えに注意してください。ポイントは角度と高さに関して均一に分布しますが、エリア全体に均一に分布することはありません。それらは先端でより密に分布します。
円柱または円錐上に直接ポイントを生成する方が簡単です。
これを行ってからしばらく経ちましたが、円柱の軸をパラメータ化してから、各ポイントについてその高さで円をパラメータ化します。これにより、サーフェス上にポイントが作成されます。円の半径は円柱の半径です。
円錐の場合、底辺から頂点に移動するときに円の半径を小さくする必要があります。
点を座標r、a、hで定義するとします。ここで、rは「半径」(中心から通る垂直軸からの距離)、aは極座標での角度、hはその高さです。
円柱の場合(半径Rと高さH ): 個別に選択
累積分布 (二次単項式) は簡単に反転できるため、このような三角分布からサンプリングすることは難しくありません (この記事を参照)。また、この答えは直感に基づいていますが、円柱上で得られた分布が均一であることを証明することは難しくありません。
円錐(半径Rと高さH )の場合: を選択
繰り返しますが、累積分布は簡単に可逆であるため、 hのサンプリングは簡単なはずです。
編集。形状の表面に点を生成することを意図している場合、解決策はより簡単です。
シリンダー:選択
コーン: 選択
他の回答はすでにシリンダーケースをかなりよくカバーしています。コーンの場合、状況は少し難しくなります。ポイントの密度を一定に保つには、半径の変化を補正する必要があります。
これを行うには、ポイント間の距離を選択することから始めます。円錐の軸に沿って移動すると、その高さで円周が計算され、円周がポイント間の直線距離で除算されてポイントの数が得られます。次に、2pi ラジアン (または 360 度など) をポイント数で割り、その半径の角距離を取得します。
必要な精度に応じて、次の円を計算しているときに、1 つの円の残りを追跡できます。たとえば、xxx.4 ポイントを必要とする 2 つの円が連続している場合、単独で見るとそれぞれを切り捨てますが、それらを一緒に見ると、xxx.8 ポイントになるので、次のようにする必要があります。 1 つを切り捨て、もう 1 つを切り上げて、全体的な密度をできるだけ正しい値に近づけます。
明らかではありませんが、後者は円柱にも適用できることに注意してください。通常、点の各円を分配する際に丸めがあります。
それらの答えを擬似コードに入れるには:
円柱の場合、cylinderRadiusとcylinderHeightを指定します。
angle = random number between 0 & 360
x = cos(pi/180*angle)*cylinderRadius
y = sin(pi/180*angle)*cylinderRadius
z = random number between 0 and cylinderHeight.
円錐の場合、coneRadius、coneHeightを指定します。
angle = random number between 0 & 360
z = random number between 0 and coneHeight
thisRadius = coneRadius * (1-(z/coneHeight)); //This gives a decreasing radius as height increases.
x = cos(pi/180*angle)*thisRadius
y = sin(pi/180*angle)*thisRadius
各点(x、y、z)は円柱/円錐上にあります。これらのポイントを十分に生成すると、円柱/円錐の表面にパーティクルをスポーンできますが、正確に均一に分布しない場合があります...
半径 R の円または円錐、および高さ/高さ H の均一な点の場合:
generate:
angle= uniform_random(0,2*pi)
value= uniform_random(0,1)
in either case, let:
r= R * sqrt(value)
then (using separate random numbers for each):
circle_point= point3d( r*cos(angle), r*sin(angle), H )
or:
cone_point= point3d( r*cos(angle), r*sin(angle), r*H )
円錐のベースが必要な場合は、湾曲した形状とは別に行う必要があることに注意してください。ポイントの密度が異なるパーツで同じであることを確認する簡単な方法は、パーツの面積を計算し、各パーツの比例した数のポイントを生成することです。
sqrt(value) は、ランダムポイントの密度が均一であることを確認するものです。他の質問で述べたように、これには三角分布が必要です。sqrt() を取ると、[0,1) 上の一様分布が三角分布に変わります。
円柱の場合、sqrt(); は必要ありません。曲がった部分は次のとおりです。
cylinder_point= point3d( R*cos(angle), R*sin(angle), H*value )