Javascript 使用Three.js重新划分椭球点云中的点

Javascript 使用Three.js重新划分椭球点云中的点,javascript,random,three.js,distribution,Javascript,Random,Three.js,Distribution,我最近开始尝试使用Three.js。 我尝试使用PointCloud对象创建粒子的椭球云 我使用椭球体的参数方程生成随机点,如下所示: var vertex = new THREE.Vector3(); u = Math.random() * 2 * Math.PI; v = Math.random() * Math.PI; vertex.x = Math.random() * a * Math.cos(u) * Math.sin(v); vertex.y

我最近开始尝试使用Three.js。 我尝试使用PointCloud对象创建粒子的椭球云

我使用椭球体的参数方程生成随机点,如下所示:

    var vertex = new THREE.Vector3();
    u = Math.random() * 2 * Math.PI;
    v = Math.random() * Math.PI;
    vertex.x = Math.random() * a * Math.cos(u) * Math.sin(v);
    vertex.y = Math.random() * b * Math.sin(u) * Math.sin(v);
    vertex.z = Math.random() * c * Math.cos(v);
但是,当我渲染云时,我注意到一个不寻常的数量的粒子聚集在椭球体的轴周围

我想知道这是否与Math.random()函数的分布有关,还是我遗漏了什么?请帮助我理解这一点

你可以看看它,我做了一个例子,以防它在你的浏览器上看起来不一样

编辑:按照@severin pappadeux的建议修改了代码,以避免错误分配点,但问题仍然存在

编辑: 我修改了使用Math.random()设置顶点长度的部分,即:

vertex.x = Math.random() * a * wx;
vertex.y = Math.random() * b * wy;
vertex.z = Math.random() * c * wz;
致:


颗粒分布更均匀。更有趣的是,它不会在轴所在的位置形成“十字孔”,这是我所期望的,因为Math.random()+0.1不会产生任何低于0.1的值。所以这个小把戏解决了我的问题,尽管我仍然对一个好的答案感兴趣。

分布在角度上显然是不均匀的。你所看到的相当于。我们可以尝试在单位球面向量上建立统一点,并将其与椭圆相交以生成顶点。沿途

phi   = 2.0 * Math.PI * Math.random();
csth  = 2.0 * Math.random() - 1.0;
snth  = Math.sqrt((1.0 - csth)*(1.0 + csth));
wx = snth * Math.sin(phi);
wy = snth * Math.cos(phi);
wz = csth;
(wx,wy,wz)
是单位向量。使用距离
s*(wx,wy,wz)
构建光线。将来自(0,0,0)的光线与椭圆相交,然后找到顶点

更新

我不知道问题是关于给定卷中的一致性。无论如何,要在单位球体中获得一致性,必须添加半径采样:

r = Math.pow( Math.random(), 1.0/3.0 ); // is there cubic root sqrt3() function?

然后,球体内的点将是
(r*wx,r*wy,r*wz)
,并可以相应地用
(a,b,c)
来缩放。如果要在三维椭球体内创建均匀分布的随机点云,请使用

首先,在立方体内部生成一个随机点,并忽略嵌入球体外部的点

vertex.x = 2 * Math.random() - 1;
vertex.y = 2 * Math.random() - 1;
vertex.z = 2 * Math.random() - 1;
if ( vertex.length() < 1 ) geometry.vertices.push( vertex );

three.js r.86

我最终使用了@WestLangley的解决方案,其实现方式如下(正如@Atrahasis所建议的):

while(geometry.vertices.length<20000){
var顶点=新的三个向量3();
vertex.x=2*Math.random()-1;
vertex.y=2*Math.random()-1;
vertex.z=2*Math.random()-1;
if(vertex.length()<1)geometry.vertexs.push(vertex);
}
您可以看到完整的代码(从我看到的情况来看,在Firefox上比在Chrome上看起来更好)

额外提示:从Github导入Codepen/JSFiddle等格式的原始js文件在Chrome上不起作用,因为该文件的MIME类型为“text/plain”,因此浏览器不会执行它。诀窍是替换
http://raw.github.com/
带有
http://rawgit.com/
so对于OrbitControls.js,我改变了
https://raw.githubusercontent.com/mrdoob/three.js/master/examples/js/controls/OrbitControls.js
https://rawgit.com/mrdoob/three.js/master/examples/js/controls/OrbitControls.js
成功了


感谢@SeverinPapadeux为您的有趣贡献。

真奇怪。你的钢笔坏了,我编辑过了。我在看它,我玩了一会儿。我尝试过不同的方法,直到将其简化为磁盘(检查更新的笔)。我得到了半径上的一个随机角度+随机距离。令人惊讶的是,在……上的分布也更高。。。轴心国。这简直是疯了。除非读者知道,否则我建议你将问题转移到math.stackexchange.com。谢谢你的研究。我开始怀疑这是否只是一种光学效果,因为粒子的渲染方式,而不是与点的分布联系在一起。我认为一个统计分析可能会对这个问题有所帮助。投票结果是肯定的,我从这次问答中学到了很多东西,感谢你提出了这个有趣的观点。我按照你的建议编辑了,但问题似乎仍然存在。有什么想法吗?@GaussianBlurs我不清楚,你编辑了这个问题,那么你还有问题吗?@GaussianBlurs和我在你提供的代码笔链接上没有看到任何东西-使用ChromeYes,javascript控制台说“拒绝执行脚本[…],因为它的MIME类型('text/plain'))不可执行,并且启用了严格的MIME类型检查”。不知道为什么会发生这种情况,所以我做了一个,告诉我它是否有效。所以我将OrbitControl.js粘贴到笔中,它就起作用了。但在进入重要部分之前,还有很长的路要走。。。此外,它在Chrome/MacOSXYosemite上的外观与在Firefox/Win7上的完全不同,这与我提出的方法基本相同。在球体上均匀分布,然后缩放并拉伸到椭圆。唯一的区别是,我使用直接采样(但使用三角函数),而您使用接受-拒绝方法(但仅使用乘法)。我尝试了您的方法,但最终得到了一个立方体形状,请参见,但是点看起来是均匀分布的。
vertex.length()
not
vertex.length
@severinpapapadeux这个答案中的方法在球体的体积内生成均匀密度的点。@WestLangley好吧,那么这不是问题所在。最初的问题和实现是关于椭圆表面上的一致点
vertex.x = 2 * Math.random() - 1;
vertex.y = 2 * Math.random() - 1;
vertex.z = 2 * Math.random() - 1;
if ( vertex.length() < 1 ) geometry.vertices.push( vertex );
var pointCloud = new THREE.Points( geometry, material );
pointCloud.scale.set( a, b, c );
while(geometry.vertices.length < 20000) {
    var vertex = new THREE.Vector3();
    vertex.x = 2 * Math.random() - 1;
    vertex.y = 2 * Math.random() - 1;
    vertex.z = 2 * Math.random() - 1;
    if(vertex.length() < 1) geometry.vertices.push(vertex);
}