Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/image-processing/2.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
Math 麦克的d3js集群部队布局图IV区块_Math_D3.js_Visualization_Data Visualization - Fatal编程技术网

Math 麦克的d3js集群部队布局图IV区块

Math 麦克的d3js集群部队布局图IV区块,math,d3.js,visualization,data-visualization,Math,D3.js,Visualization,Data Visualization,我是d3js的新手,我才刚刚开始 我正在尝试Mike在他的一个模块中编写的集群布局示例。 我用我的代码让它在我的机器上工作,但我真的不喜欢盲目地复制代码而不理解它 然而,我很难理解“集群”和“碰撞”函数背后的数学,以及它们是如何工作的 谁能解释一下吗?谢谢你的帮助 让我们看看每种方法,我会尽我所能对其进行评论 簇 首先,呼叫方: function tick(e) { node .each(cluster(10 * e.alpha * e.alpha)) //for each no

我是d3js的新手,我才刚刚开始

我正在尝试Mike在他的一个模块中编写的集群布局示例。

我用我的代码让它在我的机器上工作,但我真的不喜欢盲目地复制代码而不理解它

然而,我很难理解“集群”和“碰撞”函数背后的数学,以及它们是如何工作的


谁能解释一下吗?谢谢你的帮助

让我们看看每种方法,我会尽我所能对其进行评论

首先,呼叫方:

 function tick(e) {
  node
    .each(cluster(10 * e.alpha * e.alpha)) //for each node on each tick call function returned by cluster function
                                           //pass in alpha cooling parameter to collide
  ...
我不会在这里重复关于滴答事件如何工作的解释。问题很清楚

职能:

// returns a closure wrapping the cooling
// alpha (so it can be used for every node on the tick)
function cluster(alpha) {
  return function(d) { // d here is the datum on the node 
    var cluster = clusters[d.cluster]; // clusters is a hash-map, the key is an index of the 10 clusters, the value is an object where d.cluster is the center node in that cluster
    if (cluster === d) return;  // if we are on the center node, do nothing
    var x = d.x - cluster.x, // distance on x of node to center node
        y = d.y - cluster.y, // distance on y of node to center node
        l = Math.sqrt(x * x + y * y), // distance of node to center node (Pythagorean theorem)
        r = d.radius + cluster.radius; // radius of node, plus radius of center node (the center node is always the largest one in the cluster)
    if (l != r) { // if the node is not adjacent to the center node
      l = (l - r) / l * alpha; //find a length that is slightly closer, this provides the illusion of it moving towards the center on each tick
      d.x -= x *= l; // move node closer to center node
      d.y -= y *= l; 
      cluster.x += x; // move center node closer to node
      cluster.y += y;
    }
  };
}
碰撞

碰撞函数有点复杂。在我们深入研究它之前,您需要了解什么是四叉树以及Bostock为什么要使用它。如果您想确定两个元素是否冲突,那么简单的算法将是循环外部和内部元素,将每个元素与其他元素进行比较。当然,这在计算上是昂贵的,尤其是在每一个刻度上。这就是四叉树试图解决的问题:

四叉树递归地将二维空间划分为正方形,将每个正方形划分为四个大小相等的正方形。每个不同的点存在于唯一的叶节点中;重合点由链接列表表示。四叉树可以加速各种空间操作,例如用于计算多体力、碰撞检测和搜索附近点的Barnes–Hut近似

这是什么意思?首先,看看这个。用我自己简化的话来说,它的意思是:取一个二维空间,把它分成四个象限。如果任何象限包含4个或更少节点,则停止。如果象限包含四个以上的节点,请将其再次划分为四个象限。重复此操作,直到每个象限/子象限包含4个或更少的节点。现在,当我们寻找碰撞时,我们的内部循环不再循环节点,而是循环象限。如果象限没有碰撞,则移动到下一个象限。这是一个很大的优化

现在进入代码:

// returns a closure wrapping the cooling
// alpha (so it can be used for every node on the tick)
// and the quadtree
function collide(alpha) {
  // create quadtree from our nodes
  var quadtree = d3.geom.quadtree(nodes);
  return function(d) { // d is the datum on the node
    var r = d.radius + maxRadius + Math.max(padding, clusterPadding), // r is the radius of the node circle plus padding
        nx1 = d.x - r, // nx1, nx2, ny1, ny2 are the bounds of collision detection on the node
        nx2 = d.x + r,
        ny1 = d.y - r,
        ny2 = d.y + r;
    quadtree.visit(function(quad, x1, y1, x2, y2) { // visit each quadrant
      if (quad.point && (quad.point !== d)) { // if the quadrant is a point (a node and not a sub-quadrant) and that point is not our current node
        var x = d.x - quad.point.x, // distance on x of node to quad node
            y = d.y - quad.point.y, // distance on y of node to quad node
            l = Math.sqrt(x * x + y * y), // distance of node to quad node (Pythagorean theorem)
            r = d.radius + quad.point.radius + (d.cluster === quad.point.cluster ? padding : clusterPadding); // radius of node in quadrant
        if (l < r) { // if there is a collision
          l = (l - r) / l * alpha; // re-position nodes
          d.x -= x *= l;  
          d.y -= y *= l;
          quad.point.x += x;
          quad.point.y += y;
        }
      }
      // This is important, it determines if the quadrant intersects
      // with the node.  If it does not, it returns false
      // and we no longer visit and sub-quadrants or nodes
      // in our quadrant, if true it descends into it
      return x1 > nx2 || x2 < nx1 || y1 > ny2 || y2 < ny1;
    });
  };
}

嘿谢谢它确实有用。如果可能,请为collide提供相同的。