Java 如何对 Path2D 进行三角剖分?
How does Java triangulate a Path2D?
我正在开发一个应用程序,该应用程序从 TrueType 字体解析字形数据并将其转换为多边形以便使用 OpenGL ES 2.0 进行渲染。
我已经设法将字形数据转换为离散指令,例如 MOVE_TO
、LINE_TO
、QUAD_TO
和 CLOSE
,类似于 Java的 Path2D
class。我然后triangulate这些路径进行渲染。
我遇到的问题是我似乎以 non-standard 的方式处理这些指令,因为我可以有效地渲染一些字体但无法渲染其他字体,如下所示。经过一些测试后,这似乎是我在 LINE_TO
和 BEZIER_TO
指令之间移动时使用的决策逻辑,但我找不到与这两种字体兼容的序列。
是否有关于如何对 Java 的 Path2D
数据进行三角剖分的在线文档?
1.正确呈现的字形 ('c').
2。来自不同字体 ('c') 的错误呈现的字形。
在下面的代码片段中,我选择要绘制三角测量的点。无论我们是在曲线的内侧还是外侧,我们都会绘制贝塞尔曲线的末端或贝塞尔控制点。贝塞尔曲线正确地单独呈现给这段代码。
switch(lVectorPathComponent) {
case MOVE_TO :
/* Append the current vertex to PolygonPoints. */
if((lLastPathComponent == EVectorPathComponent.BEZIER_TO || lLastPathComponent == EVectorPathComponent.MOVE_TO)) {
lPolygonPoints.add(new PolygonPoint(pVectorPath.getPathData()[i + 1], pVectorPath.getPathData()[i + 2]));
}
/* Initialize the start location of the path. */
lStartX = pVectorPath.getPathData()[i + 1];
lStartY = pVectorPath.getPathData()[i + 2];
break;
case LINE_TO :
if(lLastPathComponent != EVectorPathComponent.MOVE_TO) {
lPolygonPoints.add(new PolygonPoint(pVectorPath.getPathData()[i + 1], pVectorPath.getPathData()[i + 2]));
}
else {
if((lNextPathComponent == EVectorPathComponent.LINE_TO || lNextPathComponent == EVectorPathComponent.BEZIER_TO)) {
lPolygonPoints.add(new PolygonPoint(pVectorPath.getPathData()[i + 1], pVectorPath.getPathData()[i + 2]));
}
}
break;
case BEZIER_TO :
if(VectorPathGlobal.onCalculateBezierDirection(pVectorPath, i) == pVectorPath.getWindingOrder()) {
if(!(lLastPathComponent == EVectorPathComponent.LINE_TO && lNextPathComponent == EVectorPathComponent.BEZIER_TO)) {
lPolygonPoints.add(new PolygonPoint(pVectorPath.getPathData()[i - 2], pVectorPath.getPathData()[i - 1])); /* Last X, Y */
lPolygonPoints.add(new PolygonPoint(pVectorPath.getPathData()[i + 1], pVectorPath.getPathData()[i + 2])); /* Control Point */
lPolygonPoints.add(new PolygonPoint(pVectorPath.getPathData()[i + 3], pVectorPath.getPathData()[i + 4])); /* Bezier end X, Y */
}
}
else {
lPolygonPoints.add(new PolygonPoint(pVectorPath.getPathData()[i + 3], pVectorPath.getPathData()[i + 4]));
}
break;
case CLOSE :
lPolygonPoints.add(new PolygonPoint(lStartX, lStartY));
break;
}
}
正确渲染的曲线由这些命令组成:
MOVE_TO x:121.0 y:682.0
BEZIER_TO cx:121.0 cy:840.0 x:164.0 y:969.0
BEZIER_TO cx:208.0 cy:1098.0 x:289.0 y:1189.0
BEZIER_TO cx:370.0 cy:1281.0 x:485.0 y:1330.0
BEZIER_TO cx:601.0 cy:1380.0 x:746.0 y:1380.0
BEZIER_TO cx:797.0 cy:1380.0 x:838.0 y:1374.0
BEZIER_TO cx:880.0 cy:1369.0 x:914.0 y:1360.0
BEZIER_TO cx:949.0 cy:1351.0 x:978.0 y:1339.0
BEZIER_TO cx:1007.0 cy:1327.0 x:1033.0 y:1314.0
LINE_TO x:978.0 y:1184.0
BEZIER_TO cx:929.0 cy:1207.0 x:872.0 y:1220.0
BEZIER_TO cx:816.0 cy:1234.0 x:746.0 y:1234.0
BEZIER_TO cx:650.0 cy:1234.0 x:571.0 y:1202.0
BEZIER_TO cx:492.0 cy:1170.0 x:435.0 y:1102.0
BEZIER_TO cx:379.0 cy:1035.0 x:348.0 y:931.0
BEZIER_TO cx:317.0 cy:827.0 x:317.0 y:682.0
BEZIER_TO cx:317.0 cy:537.0 x:349.0 y:432.0
BEZIER_TO cx:382.0 cy:327.0 x:441.0 y:259.0
BEZIER_TO cx:500.0 cy:191.0 x:583.0 y:158.0
BEZIER_TO cx:666.0 cy:126.0 x:768.0 y:126.0
BEZIER_TO cx:811.0 cy:126.0 x:847.0 y:131.0
BEZIER_TO cx:884.0 cy:137.0 x:915.0 y:146.0
BEZIER_TO cx:946.0 cy:155.0 x:972.0 y:165.0
BEZIER_TO cx:998.0 cy:176.0 x:1020.0 y:186.0
LINE_TO x:1062.0 y:58.0
BEZIER_TO cx:1009.0 cy:25.0 x:933.0 y:2.0
BEZIER_TO cx:858.0 cy:-20.0 x:746.0 y:-20.0
BEZIER_TO cx:601.0 cy:-20.0 x:485.0 y:30.0
BEZIER_TO cx:370.0 cy:81.0 x:289.0 y:173.0
BEZIER_TO cx:208.0 cy:265.0 x:164.0 y:394.0
BEZIER_TO cx:121.0 cy:524.0 x:121.0 y:682.0
错误渲染的曲线使用了这些:
MOVE_TO x:831.0 y:1391.0
BEZIER_TO cx:556.0 cy:1391.0 x:398.0 y:1215.0
BEZIER_TO cx:240.0 cy:1039.0 x:240.0 y:733.0
BEZIER_TO cx:240.0 cy:420.0 x:389.0 y:247.0
BEZIER_TO cx:538.0 cy:74.0 x:815.0 y:74.0
BEZIER_TO cx:999.0 cy:74.0 x:1153.0 y:121.0
LINE_TO x:1153.0 y:31.0
BEZIER_TO cx:1008.0 cy:-20.0 x:791.0 y:-20.0
BEZIER_TO cx:483.0 cy:-20.0 x:306.0 y:179.0
BEZIER_TO cx:129.0 cy:378.0 x:129.0 y:735.0
BEZIER_TO cx:129.0 cy:958.0 x:213.0 y:1128.0
BEZIER_TO cx:298.0 cy:1298.0 x:456.0 y:1390.0
BEZIER_TO cx:615.0 cy:1483.0 x:825.0 y:1483.0
BEZIER_TO cx:1039.0 cy:1483.0 x:1208.0 y:1403.0
LINE_TO x:1167.0 y:1311.0
BEZIER_TO cx:1007.0 cy:1391.0 x:831.0 y:1391.0
是的,代码没问题。下面的代码使用标准 Path2D quadTo/curveTo。也许它与 even-odd 缠绕规则等有关。
public class JavaGUI extends JPanel {
public static void main(String[] args) {
final JFrame f = new JFrame("Glyphs");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new JavaGUI());
f.pack();
f.setLocationRelativeTo(null);
EventQueue.invokeLater(() -> {
f.setVisible(true);
});
}
public JavaGUI() {
setPreferredSize(new Dimension(600, 600));
setBackground(new Color(0xDDEEFF));
}
private double x0;
private double y0;
@Override
public void paintComponent(Graphics g) {
final String aString = "c";
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
double scale = 0.25;
g2d.translate(100, 100);
g2d.scale(scale, scale);
Path2D.Double path = new Path2D.Double(); // May add rule and such.
moveTo(path, 121.0, 682.0);
bezierTo(path, 121.0, 840.0, 164.0, 969.0);
bezierTo(path, 208.0, 1098.0, 289.0, 1189.0);
bezierTo(path, 370.0, 1281.0, 485.0, 1330.0);
bezierTo(path, 601.0, 1380.0, 746.0, 1380.0);
bezierTo(path, 797.0, 1380.0, 838.0, 1374.0);
bezierTo(path, 880.0, 1369.0, 914.0, 1360.0);
bezierTo(path, 949.0, 1351.0, 978.0, 1339.0);
bezierTo(path, 1007.0, 1327.0, 1033.0, 1314.0);
lineTo(path, 978.0, 1184.0);
bezierTo(path, 929.0, 1207.0, 872.0, 1220.0);
bezierTo(path, 816.0, 1234.0, 746.0, 1234.0);
bezierTo(path, 650.0, 1234.0, 571.0, 1202.0);
bezierTo(path, 492.0, 1170.0, 435.0, 1102.0);
bezierTo(path, 379.0, 1035.0, 348.0, 931.0);
bezierTo(path, 317.0, 827.0, 317.0, 682.0);
bezierTo(path, 317.0, 537.0, 349.0, 432.0);
bezierTo(path, 382.0, 327.0, 441.0, 259.0);
bezierTo(path, 500.0, 191.0, 583.0, 158.0);
bezierTo(path, 666.0, 126.0, 768.0, 126.0);
bezierTo(path, 811.0, 126.0, 847.0, 131.0);
bezierTo(path, 884.0, 137.0, 915.0, 146.0);
bezierTo(path, 946.0, 155.0, 972.0, 165.0);
bezierTo(path, 998.0, 176.0, 1020.0, 186.0);
lineTo(path, 1062.0, 58.0);
bezierTo(path, 1009.0, 25.0, 933.0, 2.0);
bezierTo(path, 858.0, -20.0, 746.0, -20.0);
bezierTo(path, 601.0, -20.0, 485.0, 30.0);
bezierTo(path, 370.0, 81.0, 289.0, 173.0);
bezierTo(path, 208.0, 265.0, 164.0, 394.0);
bezierTo(path, 121.0, 524.0, 121.0, 682.0);
path.closePath();
g2d.setColor(Color.RED);
g2d.fill(path);
// ------
path = new Path2D.Double(); // May add rule and such.
moveTo(path, 831.0, 1391.0);
bezierTo(path, 556.0, 1391.0, 398.0, 1215.0);
bezierTo(path, 240.0, 1039.0, 240.0, 733.0);
bezierTo(path, 240.0, 420.0, 389.0, 247.0);
bezierTo(path, 538.0, 74.0, 815.0, 74.0);
bezierTo(path, 999.0, 74.0, 1153.0, 121.0);
lineTo(path, 1153.0, 31.0);
bezierTo(path, 1008.0, -20.0, 791.0, -20.0);
bezierTo(path, 483.0, -20.0, 306.0, 179.0);
bezierTo(path, 129.0, 378.0, 129.0, 735.0);
bezierTo(path, 129.0, 958.0, 213.0, 1128.0);
bezierTo(path, 298.0, 1298.0, 456.0, 1390.0);
bezierTo(path, 615.0, 1483.0, 825.0, 1483.0);
bezierTo(path, 1039.0, 1483.0, 1208.0, 1403.0);
lineTo(path, 1167.0, 1311.0);
bezierTo(path, 1007.0, 1391.0, 831.0, 1391.0 );
path.closePath();
g2d.setColor(new Color(0x8800CC00, true));
g2d.fill(path);
g2d.scale(1/scale, 1/scale);
}
private void bezierTo(Path2D.Double path, double cx, double cy,
double x, double y) {
path.quadTo(cx, cy, x, y);
//path.curveTo(x0, y0, cx, cy, x, y);
x0 = x;
y0 = y;
}
private void moveTo(Path2D.Double path, double x, double y) {
path.moveTo(x, y);
x0 = x;
y0 = y;
}
private void lineTo(Path2D.Double path, double x, double y) {
path.lineTo(x, y);
x0 = x;
y0 = y;
}
}
我发现 LibTess2 中使用的曲面细分方法与 Java 的 Path2D 三角剖分兼容。
在我最初的问题中,我遇到的问题是我使用的顶点三角剖分 Poly2Tri, which doesn't support vertices that lie on the edge of the polygon; because of this issue, a few strange triangles were being generated that seemed to ramp down to the origin. LibTess2 also struggles to triangulate non-simple polygons, however upon detection of conflicting vertices, it allows the user to provide a method for resolving the conflict via it's combine()
method callback. By making an equality between conflicting vertices, erroneous tessellation could be resolved, which results in a correctly triangulated glyph. earcut-j 也足够强大以处理这些顶点。
我正在开发一个应用程序,该应用程序从 TrueType 字体解析字形数据并将其转换为多边形以便使用 OpenGL ES 2.0 进行渲染。
我已经设法将字形数据转换为离散指令,例如 MOVE_TO
、LINE_TO
、QUAD_TO
和 CLOSE
,类似于 Java的 Path2D
class。我然后triangulate这些路径进行渲染。
我遇到的问题是我似乎以 non-standard 的方式处理这些指令,因为我可以有效地渲染一些字体但无法渲染其他字体,如下所示。经过一些测试后,这似乎是我在 LINE_TO
和 BEZIER_TO
指令之间移动时使用的决策逻辑,但我找不到与这两种字体兼容的序列。
是否有关于如何对 Java 的 Path2D
数据进行三角剖分的在线文档?
1.正确呈现的字形 ('c').
2。来自不同字体 ('c') 的错误呈现的字形。
在下面的代码片段中,我选择要绘制三角测量的点。无论我们是在曲线的内侧还是外侧,我们都会绘制贝塞尔曲线的末端或贝塞尔控制点。贝塞尔曲线正确地单独呈现给这段代码。
switch(lVectorPathComponent) {
case MOVE_TO :
/* Append the current vertex to PolygonPoints. */
if((lLastPathComponent == EVectorPathComponent.BEZIER_TO || lLastPathComponent == EVectorPathComponent.MOVE_TO)) {
lPolygonPoints.add(new PolygonPoint(pVectorPath.getPathData()[i + 1], pVectorPath.getPathData()[i + 2]));
}
/* Initialize the start location of the path. */
lStartX = pVectorPath.getPathData()[i + 1];
lStartY = pVectorPath.getPathData()[i + 2];
break;
case LINE_TO :
if(lLastPathComponent != EVectorPathComponent.MOVE_TO) {
lPolygonPoints.add(new PolygonPoint(pVectorPath.getPathData()[i + 1], pVectorPath.getPathData()[i + 2]));
}
else {
if((lNextPathComponent == EVectorPathComponent.LINE_TO || lNextPathComponent == EVectorPathComponent.BEZIER_TO)) {
lPolygonPoints.add(new PolygonPoint(pVectorPath.getPathData()[i + 1], pVectorPath.getPathData()[i + 2]));
}
}
break;
case BEZIER_TO :
if(VectorPathGlobal.onCalculateBezierDirection(pVectorPath, i) == pVectorPath.getWindingOrder()) {
if(!(lLastPathComponent == EVectorPathComponent.LINE_TO && lNextPathComponent == EVectorPathComponent.BEZIER_TO)) {
lPolygonPoints.add(new PolygonPoint(pVectorPath.getPathData()[i - 2], pVectorPath.getPathData()[i - 1])); /* Last X, Y */
lPolygonPoints.add(new PolygonPoint(pVectorPath.getPathData()[i + 1], pVectorPath.getPathData()[i + 2])); /* Control Point */
lPolygonPoints.add(new PolygonPoint(pVectorPath.getPathData()[i + 3], pVectorPath.getPathData()[i + 4])); /* Bezier end X, Y */
}
}
else {
lPolygonPoints.add(new PolygonPoint(pVectorPath.getPathData()[i + 3], pVectorPath.getPathData()[i + 4]));
}
break;
case CLOSE :
lPolygonPoints.add(new PolygonPoint(lStartX, lStartY));
break;
}
}
正确渲染的曲线由这些命令组成:
MOVE_TO x:121.0 y:682.0
BEZIER_TO cx:121.0 cy:840.0 x:164.0 y:969.0
BEZIER_TO cx:208.0 cy:1098.0 x:289.0 y:1189.0
BEZIER_TO cx:370.0 cy:1281.0 x:485.0 y:1330.0
BEZIER_TO cx:601.0 cy:1380.0 x:746.0 y:1380.0
BEZIER_TO cx:797.0 cy:1380.0 x:838.0 y:1374.0
BEZIER_TO cx:880.0 cy:1369.0 x:914.0 y:1360.0
BEZIER_TO cx:949.0 cy:1351.0 x:978.0 y:1339.0
BEZIER_TO cx:1007.0 cy:1327.0 x:1033.0 y:1314.0
LINE_TO x:978.0 y:1184.0
BEZIER_TO cx:929.0 cy:1207.0 x:872.0 y:1220.0
BEZIER_TO cx:816.0 cy:1234.0 x:746.0 y:1234.0
BEZIER_TO cx:650.0 cy:1234.0 x:571.0 y:1202.0
BEZIER_TO cx:492.0 cy:1170.0 x:435.0 y:1102.0
BEZIER_TO cx:379.0 cy:1035.0 x:348.0 y:931.0
BEZIER_TO cx:317.0 cy:827.0 x:317.0 y:682.0
BEZIER_TO cx:317.0 cy:537.0 x:349.0 y:432.0
BEZIER_TO cx:382.0 cy:327.0 x:441.0 y:259.0
BEZIER_TO cx:500.0 cy:191.0 x:583.0 y:158.0
BEZIER_TO cx:666.0 cy:126.0 x:768.0 y:126.0
BEZIER_TO cx:811.0 cy:126.0 x:847.0 y:131.0
BEZIER_TO cx:884.0 cy:137.0 x:915.0 y:146.0
BEZIER_TO cx:946.0 cy:155.0 x:972.0 y:165.0
BEZIER_TO cx:998.0 cy:176.0 x:1020.0 y:186.0
LINE_TO x:1062.0 y:58.0
BEZIER_TO cx:1009.0 cy:25.0 x:933.0 y:2.0
BEZIER_TO cx:858.0 cy:-20.0 x:746.0 y:-20.0
BEZIER_TO cx:601.0 cy:-20.0 x:485.0 y:30.0
BEZIER_TO cx:370.0 cy:81.0 x:289.0 y:173.0
BEZIER_TO cx:208.0 cy:265.0 x:164.0 y:394.0
BEZIER_TO cx:121.0 cy:524.0 x:121.0 y:682.0
错误渲染的曲线使用了这些:
MOVE_TO x:831.0 y:1391.0
BEZIER_TO cx:556.0 cy:1391.0 x:398.0 y:1215.0
BEZIER_TO cx:240.0 cy:1039.0 x:240.0 y:733.0
BEZIER_TO cx:240.0 cy:420.0 x:389.0 y:247.0
BEZIER_TO cx:538.0 cy:74.0 x:815.0 y:74.0
BEZIER_TO cx:999.0 cy:74.0 x:1153.0 y:121.0
LINE_TO x:1153.0 y:31.0
BEZIER_TO cx:1008.0 cy:-20.0 x:791.0 y:-20.0
BEZIER_TO cx:483.0 cy:-20.0 x:306.0 y:179.0
BEZIER_TO cx:129.0 cy:378.0 x:129.0 y:735.0
BEZIER_TO cx:129.0 cy:958.0 x:213.0 y:1128.0
BEZIER_TO cx:298.0 cy:1298.0 x:456.0 y:1390.0
BEZIER_TO cx:615.0 cy:1483.0 x:825.0 y:1483.0
BEZIER_TO cx:1039.0 cy:1483.0 x:1208.0 y:1403.0
LINE_TO x:1167.0 y:1311.0
BEZIER_TO cx:1007.0 cy:1391.0 x:831.0 y:1391.0
是的,代码没问题。下面的代码使用标准 Path2D quadTo/curveTo。也许它与 even-odd 缠绕规则等有关。
public class JavaGUI extends JPanel {
public static void main(String[] args) {
final JFrame f = new JFrame("Glyphs");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new JavaGUI());
f.pack();
f.setLocationRelativeTo(null);
EventQueue.invokeLater(() -> {
f.setVisible(true);
});
}
public JavaGUI() {
setPreferredSize(new Dimension(600, 600));
setBackground(new Color(0xDDEEFF));
}
private double x0;
private double y0;
@Override
public void paintComponent(Graphics g) {
final String aString = "c";
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
double scale = 0.25;
g2d.translate(100, 100);
g2d.scale(scale, scale);
Path2D.Double path = new Path2D.Double(); // May add rule and such.
moveTo(path, 121.0, 682.0);
bezierTo(path, 121.0, 840.0, 164.0, 969.0);
bezierTo(path, 208.0, 1098.0, 289.0, 1189.0);
bezierTo(path, 370.0, 1281.0, 485.0, 1330.0);
bezierTo(path, 601.0, 1380.0, 746.0, 1380.0);
bezierTo(path, 797.0, 1380.0, 838.0, 1374.0);
bezierTo(path, 880.0, 1369.0, 914.0, 1360.0);
bezierTo(path, 949.0, 1351.0, 978.0, 1339.0);
bezierTo(path, 1007.0, 1327.0, 1033.0, 1314.0);
lineTo(path, 978.0, 1184.0);
bezierTo(path, 929.0, 1207.0, 872.0, 1220.0);
bezierTo(path, 816.0, 1234.0, 746.0, 1234.0);
bezierTo(path, 650.0, 1234.0, 571.0, 1202.0);
bezierTo(path, 492.0, 1170.0, 435.0, 1102.0);
bezierTo(path, 379.0, 1035.0, 348.0, 931.0);
bezierTo(path, 317.0, 827.0, 317.0, 682.0);
bezierTo(path, 317.0, 537.0, 349.0, 432.0);
bezierTo(path, 382.0, 327.0, 441.0, 259.0);
bezierTo(path, 500.0, 191.0, 583.0, 158.0);
bezierTo(path, 666.0, 126.0, 768.0, 126.0);
bezierTo(path, 811.0, 126.0, 847.0, 131.0);
bezierTo(path, 884.0, 137.0, 915.0, 146.0);
bezierTo(path, 946.0, 155.0, 972.0, 165.0);
bezierTo(path, 998.0, 176.0, 1020.0, 186.0);
lineTo(path, 1062.0, 58.0);
bezierTo(path, 1009.0, 25.0, 933.0, 2.0);
bezierTo(path, 858.0, -20.0, 746.0, -20.0);
bezierTo(path, 601.0, -20.0, 485.0, 30.0);
bezierTo(path, 370.0, 81.0, 289.0, 173.0);
bezierTo(path, 208.0, 265.0, 164.0, 394.0);
bezierTo(path, 121.0, 524.0, 121.0, 682.0);
path.closePath();
g2d.setColor(Color.RED);
g2d.fill(path);
// ------
path = new Path2D.Double(); // May add rule and such.
moveTo(path, 831.0, 1391.0);
bezierTo(path, 556.0, 1391.0, 398.0, 1215.0);
bezierTo(path, 240.0, 1039.0, 240.0, 733.0);
bezierTo(path, 240.0, 420.0, 389.0, 247.0);
bezierTo(path, 538.0, 74.0, 815.0, 74.0);
bezierTo(path, 999.0, 74.0, 1153.0, 121.0);
lineTo(path, 1153.0, 31.0);
bezierTo(path, 1008.0, -20.0, 791.0, -20.0);
bezierTo(path, 483.0, -20.0, 306.0, 179.0);
bezierTo(path, 129.0, 378.0, 129.0, 735.0);
bezierTo(path, 129.0, 958.0, 213.0, 1128.0);
bezierTo(path, 298.0, 1298.0, 456.0, 1390.0);
bezierTo(path, 615.0, 1483.0, 825.0, 1483.0);
bezierTo(path, 1039.0, 1483.0, 1208.0, 1403.0);
lineTo(path, 1167.0, 1311.0);
bezierTo(path, 1007.0, 1391.0, 831.0, 1391.0 );
path.closePath();
g2d.setColor(new Color(0x8800CC00, true));
g2d.fill(path);
g2d.scale(1/scale, 1/scale);
}
private void bezierTo(Path2D.Double path, double cx, double cy,
double x, double y) {
path.quadTo(cx, cy, x, y);
//path.curveTo(x0, y0, cx, cy, x, y);
x0 = x;
y0 = y;
}
private void moveTo(Path2D.Double path, double x, double y) {
path.moveTo(x, y);
x0 = x;
y0 = y;
}
private void lineTo(Path2D.Double path, double x, double y) {
path.lineTo(x, y);
x0 = x;
y0 = y;
}
}
我发现 LibTess2 中使用的曲面细分方法与 Java 的 Path2D 三角剖分兼容。
在我最初的问题中,我遇到的问题是我使用的顶点三角剖分 Poly2Tri, which doesn't support vertices that lie on the edge of the polygon; because of this issue, a few strange triangles were being generated that seemed to ramp down to the origin. LibTess2 also struggles to triangulate non-simple polygons, however upon detection of conflicting vertices, it allows the user to provide a method for resolving the conflict via it's combine()
method callback. By making an equality between conflicting vertices, erroneous tessellation could be resolved, which results in a correctly triangulated glyph. earcut-j 也足够强大以处理这些顶点。