将svg路径转换为多边形,以便在Javascript Clipper中使用
Convert an SVG-path to polygons for use within Javascript Clipper
我正在尝试使用JS Clipper对SVG路径(包含二次和三次bezier)执行布尔运算。
JS Clipper从多边形开始,然后执行操作,然后似乎将它们转换回SVG路径。
下面的函数给出了一个SVG路径,但是下面的例子从两个多边形开始。
函数示例:
// Polygon Arrays are expanded for better readability
function clip() {
var subj_polygons = [
[{
X: 10,
Y: 10
}, {
X: 110,
Y: 10
}, {
X: 110,
Y: 110
}, {
X: 10,
Y: 110
}],
[{
X: 20,
Y: 20
}, {
X: 20,
Y: 100
}, {
X: 100,
Y: 100
}, {
X: 100,
Y: 20
}]
];
var clip_polygons = [
[{
X: 50,
Y: 50
}, {
X: 150,
Y: 50
}, {
X: 150,
Y: 150
}, {
X: 50,
Y: 150
}],
[{
X: 60,
Y: 60
}, {
X: 60,
Y: 140
}, {
X: 140,
Y: 140
}, {
X: 140,
Y: 60
}]
];
var scale = 100;
subj_polygons = scaleup(subj_polygons, scale);
clip_polygons = scaleup(clip_polygons, scale);
var cpr = new ClipperLib.Clipper();
cpr.AddPolygons(subj_polygons, ClipperLib.PolyType.ptSubject);
cpr.AddPolygons(clip_polygons, ClipperLib.PolyType.ptClip);
var subject_fillType = ClipperLib.PolyFillType.pftNonZero;
var clip_fillType = ClipperLib.PolyFillType.pftNonZero;
var clipTypes = [ClipperLib.ClipType.ctUnion];
var clipTypesTexts = "Union";
var solution_polygons, svg, cont = document.getElementById('svgcontainer');
var i;
for (i = 0; i < clipTypes.length; i++) {
solution_polygons = new ClipperLib.Polygons();
cpr.Execute(clipTypes[i], solution_polygons, subject_fillType, clip_fillType);
console.log(polys2path(solution_polygons, scale));
}
}
// helper function to scale up polygon coordinates
function scaleup(poly, scale) {
var i, j;
if (!scale) scale = 1;
for (i = 0; i < poly.length; i++) {
for (j = 0; j < poly[i].length; j++) {
poly[i][j].X *= scale;
poly[i][j].Y *= scale;
}
}
return poly;
}
// converts polygons to SVG path string
function polys2path(poly, scale) {
var path = "",
i, j;
if (!scale) scale = 1;
for (i = 0; i < poly.length; i++) {
for (j = 0; j < poly[i].length; j++) {
if (!j) path += "M";
else path += "L";
path += (poly[i][j].X / scale) + ", " + (poly[i][j].Y / scale);
}
path += "Z";
}
return path;
}
我想你的意思是某种svg路径到多边形转换。
我已经找了很多,但没有找到任何可靠的和开箱即用的解决方案。
SVG路径可以包含10个不同的段,如果我们同时考虑相对和绝对坐标,则可以包含20个。它们在路径元素的d属性中用字母表示:相对的是mhvlcqastz
,绝对的是MHVLCQASTZ
。每一个都有不同的属性,a
(椭圆弧)是最复杂的一个。最实用和最灵活的类型是c
(三次贝塞尔曲线),因为它可以以相当高的精度表示所有其他类型,如这些例子所示:http://jsbin.com/oqojan/32, http://jsbin.com/oqojan/42。
Path2Curve
-函数,可以将所有路径段转换为三次曲线,也可以处理复杂的弧到三次曲线的转换。不幸的是它有一个bug,所以它不能处理所有可能的路径段组合,但幸运的是有一个固定版本的库可用:http://jsbin.com/oqojan/32/edit(查看Javascript-window)。
当所有路径段转换为三次曲线时,它们可以转换为单独的线段。有几种方法,最好的似乎是自适应递归细分方法,该方法在曲线的急转弯处产生更多的线段,在曲线的其他部分产生更少的线段,以达到曲线保真度和低线段计数的平衡,以最大限度地提高渲染速度,但遗憾的是它不能处理所有共线情况。我成功地将AntiGrain的方法转换为Javascript,并添加了预拆分功能,该功能将曲线分割为局部极值(一阶导数根),之后AntiGrain方法还处理所有可能的共线情况:
共线水平:http://jsbin.com/ivomiq/6
不同情况的集合:http://jsbin.com/ivomiq/7
随机:http://jsbin.com/ivomiq/8
共线旋转:http://jsbin.com/ivomiq/9
以上所有样本都有两条路径在彼此的顶部,以显示自适应算法可能出现的错误:红色曲线使用非常慢的蛮力方法进行分裂,绿色曲线使用AntiGrain方法进行分裂。如果你根本没有看到红色,那么AntiGrain的方法approximate()-function
正在按预期工作。
好的,现在我们已经修复了Raphael和AntiGrain。如果我们结合这两种方法,我们可以创建一个函数,将任何svg路径元素转换为多边形(单个或多个子多边形)。我不能100%肯定这是最好或最快的方法,但它应该是可用的。当然最好是本地浏览器实现…
您可以使用De Casteljau的算法将bezier curve
分解成更小的直线,并将它们连接起来创建polygon
。
以下是De Casteljau's algorithm
- http://www.cs.mtu.edu/shene/课程/cs3621/NOTES/样条贝塞尔曲线/de-casteljau.html
- http://www.cs.mtu.edu/shene/课程/cs3621/NOTES/样条贝塞尔曲线/de-casteljau.html
- 为什么不't Javascript对我的输入值进行了一些重新检查
- 创建一个类似链接的按钮,并通过Javascript函数打开一个新的弹出窗口
- 将函数的上下文应用于javascript变量
- 使用php或javascript从facebook相册URL中删除多余的部分
- 正在添加'X'按钮,在文本字段旁边使用javascript
- 如何在JavaScript中将字符串转换为函数引用
- 模糊事件的Javascript测试
- Javascript更改图标
- 如何将HTML id分配给元素,以及如何将JavaScript应用于元素
- 如何使用WCF服务和javascript表单post上传.doc文件
- javascript结合了数组和字典
- 这是什么 ==- javascript 运算符
- 从javascript创建一个列表
- 无法在通过jQuery的ajax加载的页面中执行javascript
- Javascript:selenium Web驱动程序isDisplayed()不工作
- 如何通过ajax刷新JSF填充的javascript变量
- 如何在Javascript中将JSon对象转换为数组
- Javascript生成的表单未提交
- Javascript Clipper 中 Path 输入的格式
- 将svg路径转换为多边形,以便在Javascript Clipper中使用