Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 球面上不规则圆的填充_Javascript_Algorithm_Three.js_Geometry_Circle Pack - Fatal编程技术网

Javascript 球面上不规则圆的填充

Javascript 球面上不规则圆的填充,javascript,algorithm,three.js,geometry,circle-pack,Javascript,Algorithm,Three.js,Geometry,Circle Pack,我使用THREE.js在球体上创建点,类似于 我的数据集是一个大小不规则的圆,我希望将它们均匀地分布在球体的表面上。在网上搜索了好几个小时后,我意识到这比听起来要困难得多 以下是这一想法的实际例子: 有谁能帮我指出一个方向,找到一个算法,让我可以做到这一点?压缩比不需要非常高,理想情况下,它应该是在javascript中快速且易于计算的东西,以便在THREE.js(笛卡尔坐标系或坐标系)中渲染。效率是关键 编辑:圆半径可以变化很大。以下是使用周期表代码的示例: 您可以使用与元素周期表中相同

我使用THREE.js在球体上创建点,类似于

我的数据集是一个大小不规则的圆,我希望将它们均匀地分布在球体的表面上。在网上搜索了好几个小时后,我意识到这比听起来要困难得多

以下是这一想法的实际例子:

有谁能帮我指出一个方向,找到一个算法,让我可以做到这一点?压缩比不需要非常高,理想情况下,它应该是在javascript中快速且易于计算的东西,以便在THREE.js(笛卡尔坐标系或坐标系)中渲染。效率是关键

编辑:圆半径可以变化很大。以下是使用周期表代码的示例:

您可以使用与元素周期表中相同的代码。 那里的矩形不接触,所以你可以通过使用相同的代码来获得与圆形相同的效果

以下是他们的代码:

            var vector = new THREE.Vector3();

            for ( var i = 0, l = objects.length; i < l; i ++ ) {

                var phi = Math.acos( -1 + ( 2 * i ) / l );
                var theta = Math.sqrt( l * Math.PI ) * phi;

                var object = new THREE.Object3D();

                object.position.x = 800 * Math.cos( theta ) * Math.sin( phi );
                object.position.y = 800 * Math.sin( theta ) * Math.sin( phi );
                object.position.z = 800 * Math.cos( phi );

                vector.copy( object.position ).multiplyScalar( 2 );

                object.lookAt( vector );

                targets.sphere.push( object );

            }
var vector=new THREE.Vector3();
for(var i=0,l=objects.length;i
这里有一种尝试方法:使用模拟斥力进行迭代搜索

算法

首先,通过在曲面上以任何算法排列圆来初始化数据集。这只是为了初始化,所以不必太好。元素周期表代码将很好地工作。此外,使用每个圆的半径作为其质量值,为每个圆指定一个“质量”

现在开始迭代以收敛于一个解决方案。对于每个通过主循环的过程,请执行以下操作:

  • 计算每个圆的斥力。根据重力公式对斥力进行建模,并进行两次调整:(a)对象应相互推开,而不是相互吸引;(b)需要调整“力常数”值以适合模型的比例。根据你的数学能力,你可以在计划过程中计算出一个好的常量值;另一方面,刚开始做一点实验,你会发现一个很好的价值

  • 计算每个圆上的总力后(如果您不确定如何进行,请查阅n体问题),使用向量的长度作为移动距离,沿其总计算力的向量移动每个圆。在这里,您可能会发现必须调整“力”常量值。首先,您希望移动的长度小于球体半径的5%

  • 步骤2中的移动会将圆推离球体表面(因为它们相互排斥)。现在,沿朝向球体中心的方向将每个圆移回球体表面

  • 对于每个圆,计算从圆的旧位置到新位置的距离。移动的最大距离是主循环中此迭代的移动长度

  • 继续在主循环中迭代一段时间。随着时间的推移,随着圆的相对位置稳定到符合您标准的排列,移动长度应该会越来越小。当移动长度降至某个非常小的值以下时退出循环

    调整

    您可能会发现,您必须调整力计算以使算法收敛于某个解。如何调整取决于您所寻找的结果类型。首先调整力常数。如果这不起作用,则可能必须向上或向下更改质量值。或者在力计算中更改半径的指数。例如,与此相反:

    f = ( k * m[i] * m[j] ) / ( r * r );
    
    你可以试试这个:

    f = ( k * m[i] * m[j] ) / pow( r, p );
    
    然后你可以用不同的p值进行实验

    您还可以试验初始分布的不同算法

    //random point on sphere of radius R
    var sphereCenters = []
    var numSpheres = 100;
    for(var i = 0; i < numSpheres; i++) {
        var R = 1.0;
        var vec = new THREE.Vector3(Math.random(), Math.random(), Math.random()).normalize();
        var sphereCenter = new THREE.Vector3().copy(vec).multiplyScalar(R);
        sphereCenter.radius = Math.random() * 5; // RANDOM SPHERE SIZE, plug in your sizes here
        sphereCenters.push(sphereCenter);
        //Create a THREE.js sphere at sphereCenter
        ...
    
    }
    

    尝试和错误的数量将取决于您的设计目标。

    以下是一些您可以建立的东西。它将沿球体随机分布球体。稍后,我们将迭代此起点以获得均匀分布

    //random point on sphere of radius R
    var sphereCenters = []
    var numSpheres = 100;
    for(var i = 0; i < numSpheres; i++) {
        var R = 1.0;
        var vec = new THREE.Vector3(Math.random(), Math.random(), Math.random()).normalize();
        var sphereCenter = new THREE.Vector3().copy(vec).multiplyScalar(R);
        sphereCenter.radius = Math.random() * 5; // RANDOM SPHERE SIZE, plug in your sizes here
        sphereCenters.push(sphereCenter);
        //Create a THREE.js sphere at sphereCenter
        ...
    
    }
    
    //半径为R的球体上的随机点
    变量sphereCenters=[]
    var numSpheres=100;
    对于(变量i=0;i
    然后运行以下代码几次,以有效地打包球体:

    for(var i = 0; i < sphereCenters.length; i++) {
        for(var j = 0; j < sphereCenters.length; j++) {
            if(i === j) continue;
            //calculate the distance between sphereCenters[i] and sphereCenters[j]
            var dist = new THREE.Vector3().copy(sphereCenters[i]).sub(sphereCenters[j]);
            if(dist.length() < sphereSize) {
                 //move the center of this sphere to to compensate
                 //how far do we have to move?
                 var mDist = sphereSize - dist.length();
                 //perturb the sphere in direction of dist magnitude mDist
                 var mVec = new THREE.Vector3().copy(dist).normalize();
                 mVec.multiplyScalar(mDist);
                 //offset the actual sphere
                 sphereCenters[i].add(mVec).normalize().multiplyScalar(R);
    
            }
        }
    }
    
    for(变量i=0;i