Javascript 使用D3.js SVG进行二维多边形布尔运算

Javascript 使用D3.js SVG进行二维多边形布尔运算,javascript,d3.js,svg,graph,Javascript,D3.js,Svg,Graph,我使用D3.js创建了两个简单的面积图,其中包含以下数据和代码-让我们称它们为图A&图B。我想使用它们根据它们的相交方式创建3个新路径/多边形 路径1=图形A-图形B 路径2=图形B-图形A 路径3=图形B-路径2或图形A和图形B交点 大多数可视化编辑器允许您执行这些布尔运算,请参见: 在D3.js中可以这样做吗 jsfiddle: 图形定义: // data var dataA = [ { x: 0, y: 100, }, { x: 100, y: 150, },

我使用D3.js创建了两个简单的面积图,其中包含以下数据和代码-让我们称它们为
图A
&
图B
。我想使用它们根据它们的相交方式创建3个新路径/多边形

  • 路径1
    =
    图形A
    -
    图形B
  • 路径2
    =
    图形B
    -
    图形A
  • 路径3
    =
    图形B
    -
    路径2
    图形A
    图形B
    交点
大多数可视化编辑器允许您执行这些布尔运算,请参见:

在D3.js中可以这样做吗


jsfiddle:

图形定义:

// data
var dataA = [
    { x: 0, y: 100, },
    { x: 100, y: 150, },
    { x: 200, y: 350, },
    { x: 300, y: 200, },
];

var dataB = [
    { x: 0, y: 200, },
    { x: 100, y: 100, },
    { x: 200, y: 250, },
    { x: 300, y: 150, },
];

// Graph shapes
    var graphA = svg.append("path")
    .datum(dataA)
    .attr("class", "area")
    .attr("d", area)
    .style({fill: '#bbbb00', opacity: 0.8});

    var graphB = svg.append("path")
    .datum(dataB)
    .attr("class", "area")
    .attr("d", area)
    .style({fill: '#666666', opacity: 0.8});
我尝试剪辑路径:

// Clipping attempts
    var graphBClip = svg.append("clipPath")
        .attr('id','graphBClip')

    graphBClip.append(graphB);

    graphA.attr("clip-path","url(#graphBClip)");

作为我评论的后续行动;我刚试过我链接的图书馆。它可以很好地处理d3(它以同样的方式接收输入,对象数组)

下面是您的
a-B
B-a
的一个快速示例:


//资料
var dataA=[{
x:0,,
y:100,
}, {
x:100,
y:150,
}, {
x:200,
y:350,
}, {
x:300,
y:200,
}, ];
变量数据=[{
x:0,,
y:200,
}, {
x:100,
y:100,
}, {
x:200,
y:250,
}];
var area=d3.svg.line()
.x(功能(d){
返回d.x;
})
.y(功能(d){
返回d.y;
});
var svg=d3.select('body')
.append('svg')
.attr('width',500)
.attr('height',500);
//图形形状
var graphA=svg.append(“路径”)
.基准(数据A)
.attr(“类别”、“区域”)
.attr(“d”,区域)
.风格({
填写:“无”
});
var graphB=svg.append(“路径”)
.基准(数据)
.attr(“类别”、“区域”)
.attr(“d”,区域)
.风格({
填写:“无”
});
var AminusB=greinerHormann.diff(数据A,数据B);
var BminusA=greinerHormann.diff(数据b,数据a);
//图形形状
AminusB.forEach(功能(d){
追加(“路径”)
.基准(d)
.attr(“类别”、“区域”)
.attr(“d”,区域)
.风格({
填充:'钢蓝',
不透明度:0.8
});
});
//图形形状
BminusA.forEach(函数(d){
追加(“路径”)
.基准(d)
.attr(“类别”、“区域”)
.attr(“d”,区域)
.风格({
填充:“橙色”,
不透明度:0.8
});
});
jsclipper(sourceforge.net/projects/jsclipper)解决方案


在你的维基文章中,有一些公认的算法:和。如果你稍微搜索一下,就会发现一个。嗯,看起来这个库并不适用于所有场景。如果我给它dataset
vardataa=[{x:0,y:0,},{x:0,y:100,},{x:100,y:150,},{x:200,y:350,},{x:300,y:200,},{x:300,y:0,}]
var-dataB=[{x:0,y:0,},{x:0,y:200,},{x:100,y:100,},{x:200,y:250,},{x:300,y:200,},{x:300,y:0,}]似乎失败了…也许是d3中的路径绘制方式导致上述数据集失败了?
// Accepts array or coordinate arrays [[{X:,Y:}]] - note X & Y must be upper case, d3.js requires lowercase
function boolean2D(subj_paths, clip_paths, clip_type) {

  var ct;

  switch (clip_type) {
    case "union":
      ct = ClipperLib.ClipType.ctUnion;
      break;
    case "difference":
      ct = ClipperLib.ClipType.ctDifference;
      break;
    case "intersection":
      ct = ClipperLib.ClipType.ctIntersection;
      break;
    case "exclusion":
      ct = ClipperLib.ClipType.ctXor;
      break;
  }

  var cpr = new ClipperLib.Clipper();

  cpr.AddPaths(subj_paths, ClipperLib.PolyType.ptSubject, true);  // true means closed path
  cpr.AddPaths(clip_paths, ClipperLib.PolyType.ptClip, true);

  var solution_paths = new ClipperLib.Paths();
  var succeeded = cpr.Execute(ct, solution_paths, ClipperLib.PolyFillType.pftNonZero, ClipperLib.PolyFillType.pftNonZero);

  return solution_paths //produces array of paths to plug into d3.js
}


aXY = boolean2D(x,y,"difference");


// convert XY to lowercase

axy = [];

aXY.forEach(function(d) {
    b = []
    d.forEach(function(c) {
      b.push({x:c.X, y:c.Y});
    });
    axy.push(b);
  });



//d3 output

var svg = d3.select('#chart').append('svg')
    .attr('width', 500)
    .attr('height', 500)
    .style('background', '#C9D7D6');

axy.forEach(function(d){
      svg.append("path")
      .attr("d", lineFunction(d))
      .style({
        fill: 'orange',
        opacity: 0.8
      });
    });