D3.js - 检测交叉区域 [英] D3.js - detect intersection area

查看:84
本文介绍了D3.js - 检测交叉区域的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

NB



此问题不重复..其他帖子正在寻找交叉点和不是交叉区域



我正在尝试检测3个圆的交叉区域,以便以不同于非交叉区域的方式处理它。 / p>

我的圈子看起来像:



此处的交叉区域不可见。到目前为止我能做的就是通过降低不透明度来显示它来得到这样的东西:





我正在寻找一种智能方法来检测这三个圈子的交叉区域。



EDIT



如果可以提供帮助,这是我的 d3.js 代码:

  //代码圈
svg.append(circle)
.attr(class,services_nodes)
.attr(cx,7 * width / 16)
.attr(cy,height / 2)
.attr(r,height / 4)
。 attr('fill',blue)

//标签代码
svg.append(text)
.attr(class,label_services)
.attr(x,7 * width / 16 - 21 * width / 265)
.attr(y,35 * height / 64)
.text(Code) ;

//咨询
svg.append(circle)
.attr(class,services_nodes)
.attr(cx,9 * width / 16)
.attr(cy,height / 2)
.attr('fill',red)
.attr('r',height / 4)

//标签咨询
svg.append(text)
.attr(class,label_services)
.attr(x, 9 *宽度/ 16)
.attr(y,35 * height / 64)
.text(咨询);

//支持
svg.append(circle)
.attr(class,services_nodes)
.attr(cx,7 * width / 16 + height / 8)
.attr(cy,height / 2 - Math.sqrt(3)* height / 8)// y +/- Math.sqrt(3)* r / 2
.attr('fill',green)
.attr('r',height / 4)

//标签支持
svg.append (text)
.attr(class,label_services)
.attr(x,7 * width / 16 + 3 * height / 64)
.attr( y,身高/ 2 - Math.sqrt(3)*身高/ 8 - 3 *身高/ 32)
.text(支持);

提前致谢!

解决方案

正如我在评论中所说,交叉区域只是从每个圆上的交叉点绘制的两个弧。借用此处的交叉点代码。

  var interPoints = intersection(x1,y1,r,x2,y2,r); 

svg.append(g)
.append(path)
.attr(d,function(){
returnM + interPoints [0] +,+ interPoints [2] +A+ r +,+ r +
0 0,1+ interPoints [1] +,+ interPoints [3 ] +A+ r +,+ r +
0 0,1+ interPoints [0] +,+ interPoints [2];
})
。 style('fill','red');

2个圈子的完整工作代码是:



 <!DOCTYPE html>< html>< head> < script data-require =d3@3.5.3data-semver =3.5.3src =// cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.js\"> < /脚本>< /头><身体GT; <脚本> var x1 = 100,y1 = 100,x2 = 150,y2 = 150,r = 70; var svg = d3.select('body')。append('svg')。attr('width',600).attr('height',600); svg.append('circle')。attr('cx',x1).attr('cy',y1).attr('r',r).style('fill','steelblue'); svg.append('circle')。attr('cx',x2).attr('cy',y2).attr('r',r).style('fill','orange'); var interPoints = intersection(x1,y1,r,x2,y2,r); svg.append(g)。append(path)。attr(d,function(){returnM+ interPoints [0] +,+ interPoints [2] +A+ r +,+ r +0 0,1+ interPoints [1] +,+ interPoints [3] +A+ r +,+ r +0 0,1+ interPoints [0 ] +,+ interPoints [2];})。style('fill','red');函数交集(x0,y0,r0,x1,y1,r1){var a,dx,dy,d,h,rx,ry; var x2,y2; / * dx和dy是*圆心之间的垂直和水平距离。 * / dx = x1  -  x0; dy = y1  -  y0; / *确定中心之间的直线距离。 * / d = Math.sqrt((dy * dy)+(dx * dx)); / *检查可解决性。 * / if(d>(r0 + r1)){/ *无解。圆圈不相交。 * / return false; } if(d< Math.abs(r0  -  r1)){/ *无解。一个圆圈包含在另一个* / return false中; } / *'point 2'是穿过圆*交叉点的直线与圆*中心之间的直线相交的点。 * / / *确定从0点到2点的距离。* / a =((r0 * r0) - (r1 * r1)+(d * d))/(2.0 * d); / *确定点2的坐标。* / x2 = x0 +(dx * a / d); y2 = y0 +(dy * a / d); / *确定从点2到任一交叉点的距离。 * / h = Math.sqrt((r0 * r0) - (a * a)); / *现在从*点2确定交叉点的偏移量。* / rx = -dy *(h / d); ry = dx *(h / d); / *确定绝对交叉点。 * / var xi = x2 + rx; var xi_prime = x2  -  rx; var yi = y2 + ry; var yi_prime = y2  -  ry; return [xi,xi_prime,yi,yi_prime]; }< / script>< / body>< / html>  



在此之后,3个圆圈的交集变为:



 < !DOCTYPE html>< html>< head> < script data-require =d3@3.5.3data-semver =3.5.3src =// cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.js\"> < /脚本>< /头><身体GT; <脚本> var x1 = 150,y1 = 100,x2 = 200,y2 = 150,x3 = 100,y3 = 150,r = 70; var svg = d3.select('body')。append('svg')。attr('width',600).attr('height',600); svg.append('circle')。attr('cx',x1).attr('cy',y1).attr('r',r).style('fill','steelblue'); svg.append('circle')。attr('cx',x2).attr('cy',y2).attr('r',r).style('fill','orange'); svg.append('circle')。attr('cx',x3).attr('cy',y3).attr('r',r).style('fill','green'); var interPoints1 = intersection(x1,y1,r,x2,y2,r); var interPoints2 = intersection(x2,y2,r,x3,y3,r); var interPoints3 = intersection(x1,y1,r,x3,y3,r); svg.append(g)。append(path)。attr(d,function(){returnM+ interPoints3 [1] +,+ interPoints3 [3] +A+ r +,+ r +0 0,1+ interPoints1 [0] +,+ interPoints1 [2] +A+ r +,+ r +0 0,1+ interPoints2 [0 ] +,+ interPoints2 [2] +A+ r +,+ r +0 0,1+ interPoints3 [1] +,+ interPoints3 [3];})。style('填充','红色');函数交集(x0,y0,r0,x1,y1,r1){var a,dx,dy,d,h,rx,ry; var x2,y2; / * dx和dy是*圆心之间的垂直和水平距离。 * / dx = x1  -  x0; dy = y1  -  y0; / *确定中心之间的直线距离。 * / d = Math.sqrt((dy * dy)+(dx * dx)); / *检查可解决性。 * / if(d>(r0 + r1)){/ *无解。圆圈不相交。 * / return false; } if(d< Math.abs(r0  -  r1)){/ *无解。一个圆圈包含在另一个* / return false中; } / *'point 2'是穿过圆*交叉点的直线与圆*中心之间的直线相交的点。 * / / *确定从0点到2点的距离。* / a =((r0 * r0) - (r1 * r1)+(d * d))/(2.0 * d); / *确定点2的坐标。* / x2 = x0 +(dx * a / d); y2 = y0 +(dy * a / d); / *确定从点2到任一交叉点的距离。 * / h = Math.sqrt((r0 * r0) - (a * a)); / *现在从*点2确定交叉点的偏移量。* / rx = -dy *(h / d); ry = dx *(h / d); / *确定绝对交叉点。 * / var xi = x2 + rx; var xi_prime = x2  -  rx; var yi = y2 + ry; var yi_prime = y2  -  ry; return [xi,xi_prime,yi,yi_prime]; }< / script>< / body>< / html>  


NB

This question is not a duplicate.. Other posts are looking for the intersection points and not intersection area

I am trying to detect the intersection area of 3 circles in order to process it differently than the non-intersection zone.

My circles look like:

The intersection area here is not visible. What I could do so far is to show it by decreasing the opacity to get something like this:

I am looking for a smart way to detect the intersection zone of this three circles.

EDIT

In case that can help, here is my d3.js code:

// Code circle 
    svg.append("circle")
    .attr("class","services_nodes")
    .attr("cx",7*width/16)
    .attr("cy",height/2)
    .attr("r",height/4)
    .attr('fill', "blue")

    // Label code
    svg.append("text")
    .attr("class","label_services")
    .attr("x", 7*width/16 - 21*width/265)
    .attr("y",35*height/64)
    .text("Code");

    // Consulting
    svg.append("circle")
    .attr("class","services_nodes")
    .attr("cx",9*width/16)
    .attr("cy",height/2)
    .attr('fill', "red")
    .attr('r', height/4)

    // Label Consulting
    svg.append("text")
    .attr("class","label_services")
    .attr("x", 9*width/16)
    .attr("y",35*height/64)
    .text("Consulting");

    // Support 
    svg.append("circle")
    .attr("class","services_nodes")
    .attr("cx",7*width/16 + height/8)
    .attr("cy",height/2 - Math.sqrt(3)*height/8) // y +/- Math.sqrt(3)*r/2
    .attr('fill', "green")
    .attr('r',height/4)

    // Label Support
    svg.append("text")
    .attr("class","label_services")
    .attr("x", 7*width/16 + 3*height/64)
    .attr("y",height/2 - Math.sqrt(3)*height/8 - 3*height/32)
    .text("Support");

Thanks in advance!

解决方案

As I stated in my comments, the area of intersection is simply the two arcs drawn from the intersection points on each circle. Borrowing the intersection code from here.

var interPoints = intersection(x1, y1, r, x2, y2, r);

svg.append("g")
  .append("path")
  .attr("d", function() {
    return "M" + interPoints[0] + "," + interPoints[2] + "A" + r + "," + r +
      " 0 0,1 " + interPoints[1] + "," + interPoints[3]+ "A" + r + "," + r +
      " 0 0,1 " + interPoints[0] + "," + interPoints[2];
  })
  .style('fill', 'red');   

Full working code for 2 circles is:

<!DOCTYPE html>
<html>

<head>
  <script data-require="d3@3.5.3" data-semver="3.5.3" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.js"></script>
</head>

<body>
  <script>
    var x1 = 100,
      y1 = 100,
      x2 = 150,
      y2 = 150,
      r = 70;

    var svg = d3.select('body')
      .append('svg')
      .attr('width', 600)
      .attr('height', 600);

    svg.append('circle')
      .attr('cx', x1)
      .attr('cy', y1)
      .attr('r', r)
      .style('fill', 'steelblue');

    svg.append('circle')
      .attr('cx', x2)
      .attr('cy', y2)
      .attr('r', r)
      .style('fill', 'orange');

    var interPoints = intersection(x1, y1, r, x2, y2, r);

    svg.append("g")
      .append("path")
      .attr("d", function() {
        return "M" + interPoints[0] + "," + interPoints[2] + "A" + r + "," + r +
          " 0 0,1 " + interPoints[1] + "," + interPoints[3]+ "A" + r + "," + r +
          " 0 0,1 " + interPoints[0] + "," + interPoints[2];
      })
      .style('fill', 'red');


    function intersection(x0, y0, r0, x1, y1, r1) {
      var a, dx, dy, d, h, rx, ry;
      var x2, y2;

      /* dx and dy are the vertical and horizontal distances between
       * the circle centers.
       */
      dx = x1 - x0;
      dy = y1 - y0;

      /* Determine the straight-line distance between the centers. */
      d = Math.sqrt((dy * dy) + (dx * dx));

      /* Check for solvability. */
      if (d > (r0 + r1)) {
        /* no solution. circles do not intersect. */
        return false;
      }
      if (d < Math.abs(r0 - r1)) {
        /* no solution. one circle is contained in the other */
        return false;
      }

      /* 'point 2' is the point where the line through the circle
       * intersection points crosses the line between the circle
       * centers.  
       */

      /* Determine the distance from point 0 to point 2. */
      a = ((r0 * r0) - (r1 * r1) + (d * d)) / (2.0 * d);

      /* Determine the coordinates of point 2. */
      x2 = x0 + (dx * a / d);
      y2 = y0 + (dy * a / d);

      /* Determine the distance from point 2 to either of the
       * intersection points.
       */
      h = Math.sqrt((r0 * r0) - (a * a));

      /* Now determine the offsets of the intersection points from
       * point 2.
       */
      rx = -dy * (h / d);
      ry = dx * (h / d);

      /* Determine the absolute intersection points. */
      var xi = x2 + rx;
      var xi_prime = x2 - rx;
      var yi = y2 + ry;
      var yi_prime = y2 - ry;

      return [xi, xi_prime, yi, yi_prime];
    }
  </script>
</body>

</html>

Following this, the intersection of 3 circles becomes:

<!DOCTYPE html>
<html>

<head>
  <script data-require="d3@3.5.3" data-semver="3.5.3" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.js"></script>
</head>

<body>
  <script>
    var x1 = 150,
      y1 = 100,
      x2 = 200,
      y2 = 150,
      x3 = 100,
      y3 = 150,
      r = 70;

    var svg = d3.select('body')
      .append('svg')
      .attr('width', 600)
      .attr('height', 600);

    svg.append('circle')
      .attr('cx', x1)
      .attr('cy', y1)
      .attr('r', r)
      .style('fill', 'steelblue');

    svg.append('circle')
      .attr('cx', x2)
      .attr('cy', y2)
      .attr('r', r)
      .style('fill', 'orange');
      
    svg.append('circle')
      .attr('cx', x3)
      .attr('cy', y3)
      .attr('r', r)
      .style('fill', 'green');

    var interPoints1 = intersection(x1, y1, r, x2, y2, r);
    var interPoints2 = intersection(x2, y2, r, x3, y3, r);
    var interPoints3 = intersection(x1, y1, r, x3, y3, r);
    
    svg.append("g")
      .append("path")
      .attr("d", function() {
        return "M" + interPoints3[1] + "," + interPoints3[3] + "A" + r + "," + r +
          " 0 0,1 " + interPoints1[0] + "," + interPoints1[2] + "A" + r + "," + r +
          " 0 0,1 " + interPoints2[0] + "," + interPoints2[2] + "A" + r + "," + r +
          " 0 0,1 " + interPoints3[1] + "," + interPoints3[3];
      })
      .style('fill', 'red');

    function intersection(x0, y0, r0, x1, y1, r1) {
      var a, dx, dy, d, h, rx, ry;
      var x2, y2;

      /* dx and dy are the vertical and horizontal distances between
       * the circle centers.
       */
      dx = x1 - x0;
      dy = y1 - y0;

      /* Determine the straight-line distance between the centers. */
      d = Math.sqrt((dy * dy) + (dx * dx));

      /* Check for solvability. */
      if (d > (r0 + r1)) {
        /* no solution. circles do not intersect. */
        return false;
      }
      if (d < Math.abs(r0 - r1)) {
        /* no solution. one circle is contained in the other */
        return false;
      }

      /* 'point 2' is the point where the line through the circle
       * intersection points crosses the line between the circle
       * centers.  
       */

      /* Determine the distance from point 0 to point 2. */
      a = ((r0 * r0) - (r1 * r1) + (d * d)) / (2.0 * d);

      /* Determine the coordinates of point 2. */
      x2 = x0 + (dx * a / d);
      y2 = y0 + (dy * a / d);

      /* Determine the distance from point 2 to either of the
       * intersection points.
       */
      h = Math.sqrt((r0 * r0) - (a * a));

      /* Now determine the offsets of the intersection points from
       * point 2.
       */
      rx = -dy * (h / d);
      ry = dx * (h / d);

      /* Determine the absolute intersection points. */
      var xi = x2 + rx;
      var xi_prime = x2 - rx;
      var yi = y2 + ry;
      var yi_prime = y2 - ry;

      return [xi, xi_prime, yi, yi_prime];
    }
  </script>
</body>

</html>

这篇关于D3.js - 检测交叉区域的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆