首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将SVG路径转换为多边形,以便在Javascript Clipper中使用

将SVG路径转换为多边形,以便在Javascript Clipper中使用
EN

Stack Overflow用户
提问于 2013-03-06 20:45:05
回答 2查看 5K关注 0票数 4

我正在尝试使用JS Clipper对SVG路径(包含贝塞尔曲线,包括二次和三次)执行布尔操作。

JS Clipper从多边形开始,然后执行操作,然后似乎将它们转换回SVG路径。

下面的函数给出了一个SVG路径,但下面的示例从2个多边形开始。

下面是一个示例函数:

代码语言:javascript
复制
// 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;

}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-04-09 06:52:20

我假设您指的是某种从svg路径到多边形的转换。

我已经搜索了很多,但没有找到任何可靠的开箱即用的解决方案。

SVG路径可以由10个不同的段组成,如果我们同时考虑相对坐标和绝对坐标,则可以由20个不同的段组成。它们在path元素的d属性中表示为字母:相对的是mhvlcqastz,绝对的是MHVLCQASTZ。每一个都有不同的属性,a (椭圆弧)是最复杂的一个。最可用和最灵活的类型是c (三次贝塞尔曲线),因为它可以以相当高的精度表示所有其他类型:http://jsbin.com/oqojan/32http://jsbin.com/oqojan/42

拉斐尔JS库具有Path2Curve-function,它可以将所有路径段转换为三次曲线,也可以处理复杂的圆弧到三次曲线的转换。不幸的是,它有一个bug,所以它不能处理所有可能的路径段组合,但幸运的是,有一个固定版本的库可用:http://jsbin.com/oqojan/32/edit (查看Javascript窗口)。

将所有路径段转换为三次曲线后,可以将它们转换为单独的线段。有几种方法,最好的似乎是an adaptive recursive subdivision method,它在曲线的急转弯中生成更多的线段,而在曲线的其他部分生成更少的线段,以实现曲线保真度和线段数之间的平衡,从而最大限度地提高渲染速度,但不幸的是,它不能处理所有共线情况。我成功地将AntiGrain的方法转换为Javascript,并添加了预分割功能,该功能将曲线分割为局部极值(一阶导数根),之后AntiGrain方法还可以处理所有可能的共线情况:

共线水平:http://jsbin.com/ivomiq/6

一组不同的案例:http://jsbin.com/ivomiq/7

随机:http://jsbin.com/ivomiq/8

共线旋转:http://jsbin.com/ivomiq/9

所有上述样本都有两条路径重叠在一起,以显示自适应算法中可能存在的错误:红色曲线使用非常慢的蛮力方法分割,绿色曲线使用AntiGrain方法分割。如果您没有看到任何红色,则说明反颗粒的方法approximate()-function正在按预期工作。

好了,现在我们已经修复了拉斐尔和AntiGrain。如果我们将这两种方法结合起来,我们就可以创建一个将任何svg路径元素转换为多边形(单个或多个子多边形)的函数。我不能100%确定这是最好的还是最快的方法,但它应该是可用的。当然,最好的方法是原生浏览器实现……

票数 6
EN

Stack Overflow用户

发布于 2013-03-10 04:03:11

您可以使用De Casteljau's algorithmbezier curve拆分成更小的直线,然后将它们连接起来创建polygon

以下是De Casteljau's algorithm的一些参考资料

  • http://www.cs.mtu.edu/~shene/COURSES/cs3621/NOTES/spline/Bezier/de-casteljau.html
  • http://www.cs.mtu.edu/~shene/COURSES/cs3621/NOTES/spline/Bezier/de-casteljau.html
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15247711

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档