Math 3D:从极坐标创建球体时,避免在极点挤压

Math 3D:从极坐标创建球体时,避免在极点挤压,math,three.js,geometry,quaternions,polar-coordinates,Math,Three.js,Geometry,Quaternions,Polar Coordinates,我正在使用维基百科在Three.js中创建一个由粒子组成的球体。基于本文,我创建了一个小型的偏光器类,它使用setPolar(rho,theta,phi)获取极坐标,并返回相应的x,y,z 下面是setPolar()函数: // Rho: radius // theta θ: polar angle on Y axis // phi φ: azimuthal angle on Z axis Polarizer.prototype.setPolar = function(rho, theta,

我正在使用维基百科在Three.js中创建一个由粒子组成的球体。基于本文,我创建了一个小型的
偏光器
类,它使用
setPolar(rho,theta,phi)
获取极坐标,并返回相应的x,y,z

下面是
setPolar()
函数:

// Rho: radius
// theta θ: polar angle on Y axis
// phi φ: azimuthal angle on Z axis

Polarizer.prototype.setPolar = function(rho, theta, phi){
  // Limit values to zero
  this.rho = Math.max(0, rho);
  this.theta = Math.max(0, theta);
  this.phi = Math.max(0, phi);

  // Calculate x,y,z
  this.x = this.rho * Math.sin(this.theta) * Math.sin(this.phi);
  this.y = this.rho * Math.cos(this.theta);
  this.z = this.rho * Math.sin(this.theta) * Math.cos(this.phi);

  return this;
}
我用它来定位我的粒子,如下所示:

var tempPolarizer = new Polarizer();

for(var i = 0; i < geometry.vertices.length; i++){
  tempPolarizer.setPolar(
    50,                         // Radius of 50
    Math.random() * Math.PI,    // Theta ranges from 0 - PI
    Math.random() * 2 * Math.PI // Phi ranges from 0 - 2PI
  );

  // Set new vertex positions
  geometry.vertices[i].set(
    tempPolarizer.x,
    tempPolarizer.y,
    tempPolarizer.z
  );
}
var tempalizer=新的起偏器();
对于(var i=0;i
它工作得非常好,除了我得到了高粒子密度,或者两极的“挤压”:

我不知道如何避免这种情况发生。我曾想过将一个加权随机数传递到纬度,但我希望在不让经度减慢并聚集在极点的情况下为粒子设置动画


有没有一个不同的公式来生成一个极点没有得到那么多重量的球体?我应该使用四元数吗?

为了避免两极的高密度,我必须降低θ(纬度)接近0和π的可能性。我的意见

Math.random()*Math.PI,
对于θ,所有值的可能性相等(橙色)

Math.acos((Math.random()*2)-1)
完美地对输出进行加权,使0和PI沿球体表面(黄色)的可能性降低


现在我都不知道电线杆在哪里了

为了避免两极的高密度,我不得不降低θ(纬度)接近0和π的可能性。我的意见

Math.random()*Math.PI,
对于θ,所有值的可能性相等(橙色)

Math.acos((Math.random()*2)-1)
完美地对输出进行加权,使0和PI沿球体表面(黄色)的可能性降低

现在我都不知道电线杆在哪里了

  • 用于随机均匀抽样

    使用单位立方体中的随机点,将其作为向量处理,并将其长度设置为球体的半径。例如,C++中的类似内容:

    x=2.0*Random()-1.0;
    y=2.0*随机()-1.0;
    z=2.0*Random()-1.0;
    m=r/sqrt(x*x+y*y+z*z);
    x*=m;
    y*=m;
    z*=m;
    
    其中,
    中的随机返回数。有关更多信息,请参阅:

  • 用于均匀非随机抽样

    参见相关的QAs:

  • 用于随机均匀抽样

    使用单位立方体中的随机点,将其作为向量处理,并将其长度设置为球体的半径。例如,C++中的类似内容:

    x=2.0*Random()-1.0;
    y=2.0*随机()-1.0;
    z=2.0*Random()-1.0;
    m=r/sqrt(x*x+y*y+z*z);
    x*=m;
    y*=m;
    z*=m;
    
    其中,
    中的随机返回数。有关更多信息,请参阅:

  • 用于均匀非随机抽样

    参见相关的QAs:


  • 我会在这里寻找两种可能的解决方案,而且,更一般地说,二十面体球体是three.js中的一个额外选项,它可能很有用,具体取决于您需要如何测试噪声分布。示例:@Radio,这正是我要找的!我必须使用类似于加权随机数生成器的东西,它更可能接近0.5,而不是0或1。我会在这里寻找两种可能的解决方案,而且更一般地说,二十面体球体是three.js中的一个额外选项,这可能很有用,具体取决于您需要如何测试噪声分布。示例:@Radio,这正是我要找的!我必须使用类似于加权随机数生成器的东西,它有更高的可能性接近0.5,而不是0或1。