用于确定化合物贝塞尔曲线形状中的固体/空穴的算法

时间:2017-09-19 21:44:14

标签: svg graphics bezier

我使用nanovg库来渲染复合贝塞尔曲线形状,但nanosvg库并没有告诉我卷绕方向,也就是固体/孔洞的强度复合形状中的每个子路径。

假设所有路径都是非交叉的,假设所有路径都是非交叉的,那么什么是数学算法会告诉我哪个子路径是实心的,哪个是一个洞?

我可以计算每个子路径的面积,按区域排序,以及实体和孔之间的替代,但这仅在路径形成子集链时才有效,因此无法绘制此复合形状。

compond shape figure

1 个答案:

答案 0 :(得分:1)

该算法是SVG fill-rule定义中描述的算法。从一个点开始并将一条任意光线绘制到无穷大(嗯,一条线在你需要考虑的区域之外结束)并使用两种方法之一非零 evenodd计算路径交叉点描述。

确定交叉计数:不要一次尝试为子路径执行此操作,而是单独考虑每个路径段。大多数人的计数为零,这很好。 This library例如function用于计算三次贝塞尔曲线与直线之间的交点。查看源代码,它有详细记录。 (虽然作者对版权采取的立场并不十分清楚。)

确定路径方向:您只需确定线段的起点和终点是光线的左侧还是右侧。

  • 如果两者位于同一侧,则从左到右,从右到左计数一个。 (非零规则:0,偶数规则:+2)
  • 如果左起点且终点是正确的,则从左到右计数(+1),或者对于具有三个交叉点的三次贝塞尔计数,从左到右计数两个,右计算一个 - 向左。 (非零规则:+1,偶数规则:+3)
  • 如果起点是正确的并且终点是左边的,那么一个交叉点(非零规则:-1,偶数规则:+1)或三个交叉点(非零规则:-1,偶数规则:+3)< / LI>
  • 如果光线穿过分段点处的子路径,则必须避免两次计算交叉点。避免错误的最佳方法是将两个段处理为一个,从增加的交叉计数中减去一个,并仅确定整个起点/终点的一侧。

最后,对于非零,如果最终计数总数不为零,则内部有一个点。对于 evenodd ,如果最终计数总数为奇数,则在内部。