D3.js - 检测交叉区域

11

NB

这个问题不是重复的。其他帖子在寻找交点而不是交集区域

我正在尝试检测3个圆的交集区域,以便与非交集区域进行区别处理。

我的三个圆看起来像这样: enter image description here

这里的交集区域是看不见的。到目前为止,我能做的只是通过降低不透明度来展示它,得到类似这样的东西:

enter image description here

我正在寻找一种智能的方式来检测这三个圆的交集区域。

编辑

如果有帮助的话,这是我的d3.js代码:

// 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");

提前感谢!


2
不是的!那篇帖子是在寻找两个点的交集,而不是整个区域。下次在无法提供帮助时,请再三考虑后再建议关闭问题! - farhawa
该区域仅为连接每个圆上两点的填充弧。 - Mark
请解释一下你的解决方案。 - farhawa
1
@farhawa 我认为这篇**博客文章对你会非常有帮助。它的示例使用了venn.js**。 - Ramiz Wachtler
1
谢谢@RamisWachtler,这真的很有帮助! - farhawa
1个回答

11

如我在评论中所述,交集区域只是从每个圆上的交点处画出的两个弧。从这里借用交点代码。

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');   

完整的两个圆形的工作代码如下:

<!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>

接下来,3个圆的相交部分将变为:

<!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>


这就是我们所称之为完整的回答,谢谢你,朋友! - farhawa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接