12

是否存在可以对路径(贝塞尔曲线)执行布尔运算的 Javascript 库?

我知道 Paper.js 和 Raphael.js,但现在两者都无法执行这些操作。

4

5 回答 5

7

Paper.js 现在在其核心中具有布尔运算:

https://github.com/paperjs/paper.js/blob/master/src/path/PathItem.Boolean.js

在这里您可以看到实际操作:

http://assets.paperjs.org/boolean/

于 2013-05-07T07:46:19.547 回答
5

如果您将路径转换为多边形(例如,使用 pathelement.getPointAtLength()),那么您可以使用 Javascript Clipper,它是流行的 Angus Johnson 的 Clipper 库的 javascript 端口。

这是一个 Difference 的示例,但Union、Intersect 和 Xor也是可能的: 多边形的差异

Javascript Clipper 的页面在这里

如果 getPointAtLength() 给出的点数过多,Javascript Clipper 有一个函数 ClipperLib.Lighten(),可以显着减少点数。

该库还支持多边形偏移。查看现场演示


编辑:经过测试,我可以确认 pathelement.getPointAtLength() 最适合例如。命中测试,但在这种情况下对多边形化不太好,因为它产生的点太少或太多,并且没有考虑曲率。事实上,紧曲线需要更多点,而松曲线则需要更少。更好的是将所有路径段转换为三次曲线并使用一些自适应算法来多边形化曲线。我已经做了一些测试,可能很快就会引入一种更好的多边形化方法。

编辑:我已经设法实现了 SVG 路径多边形化功能,它可以处理所有类型的路径并且还可以展平转换。在测试了数千个随机生成的路径和转换之后,它似乎是可靠的。此外,所有可能的退化情况(曲线共线或某些点相同)都可以毫无问题地处理。尽管它已经比本机 getPointAtLength() 快很多倍且更精确,同时产生的点数要少得多,但该过程还有使用例如提高速度的空间。出租车角度而不是 atan2() 并通过删除所有 DOM 方法使代码与 Web Workers 完全兼容。我想在发布之前让它 100% 没有错误。它的理想用例是例如。对生成的多边形进行布尔运算的可能性。

于 2013-01-13T18:07:42.070 回答
2

PaperJS 布尔运算与 intersect 函数的示例

我们可以使用 PaperJS 布尔运算来做到这一点,它可以使用 SVG 路径(包括贝塞尔曲线路径)进行操作。

PaperJS 有 5 种不同的布尔运算:exclude, subtract, unite, intersect, divide. 您可以在此处查看所有这些示例。

这些操作也是同名的函数,它们返回item的对象是函数exportSVG()。它返回 true SVG Path element,它具有两条路径相交的新形状。它非常有用——您可以获取 path 属性的值,d或者您可以将此路径元素附加到新的 SVG 元素中。

paper.install(window);
window.onload = function()
{
    paper.setup('canvas');

    var p1 = 'M 24.379464,51.504463 23.434524,23.156249 38.742559,12.572916 c 0,0 29.860118,-9.0714281 17.00893,0.755953 -12.851191,9.82738 13.229166,19.465774 13.229166,19.465774 z',
        p2 = 'm 32.883928,0.28869028 c 0,0 -15.686011,1.51190452 -8.504463,7.18154712 7.181546,5.6696426 50.270836,30.0491076 26.458332,42.3333336 -23.8125,12.284226 47.058036,14.174107 47.058036,14.174107 z',
        path1 = new Path(p1),
        path2 = new Path(p2);

    path1.fillColor = 'rgba(255,0,0,.5)';
    path1.position = new Point(25, 25);

    path2.fillColor = 'rgba(0,255,0,.5)';
    path2.position = new Point(40, 25);
    
    var result = path2.intersect(path1);
    result.selected = true;
    result.fillColor = '#77f';

    //exportSVG() docu: http://paperjs.org/reference/item/#exportsvg
    var svgPathElement = result.exportSVG(),
        dPath = svgPathElement.getAttribute('d');
    
    document.querySelector('path').setAttribute('d', dPath);

    var output = document.querySelector('#output');
    output.innerHTML = '<pre><b>D value from path:</b> ' + dPath + '</pre>';
    output.innerHTML += '<xmp>HTML string of path: ' + svgPathElement.outerHTML + '</xmp>';
};
table
{
    margin-left:14px;
    padding-left:14px;
    border-left:1px solid gray;
    display:inline-block
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/paper.js/0.12.0/paper-full.min.js"></script>

<canvas id="canvas" width="75" height="75" resize></canvas>
<table><tr><td><b>Our new shape of both paths intersection in separate SVG:</b></td></tr>
<tr><td>
    <svg width="75" height="75" viewBox="0 0 75 75">
    <path fill="rgba(0,0,255,.5)" d=""/>
    </svg>
</td></tr></table>

<div id="output"></div>

有用的链接:

于 2018-12-28T06:15:29.517 回答
1

Try to use this - https://github.com/interstateone/polygons

于 2012-08-17T10:17:47.407 回答
1

有一个用于 raphael.js 的插件提供此功能 – https://github.com/poilu/raphael-boolean

于 2013-01-08T11:53:18.940 回答