我试图通过
Area.intersect()
获得两个多边形的交集,但在某些情况下我得到了一个奇怪的结果。
我的代码:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.geom.Area;
import java.awt.geom.Line2D;
import java.awt.geom.Path2D;
import java.awt.geom.PathIterator;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Main
{
public static void main(String[] args)
{
JFrame frame = new JFrame();
frame.setSize(400, 400);
frame.setLocationRelativeTo(null);
frame.setResizable(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
JPanel panel = new Panel();
frame.add(panel);
}
static class Panel extends JPanel
{
Panel()
{
setBackground(new Color(0, 50, 0));
setFocusable(true);
}
@Override
public void paintComponent(Graphics g1)
{
super.paintComponent(g1);
Graphics2D g = (Graphics2D) g1;
AffineTransform at = new AffineTransform();
at.scale(3,3);
g.transform(at);
g.setColor(Color.blue);
Path2D.Double path1 = new Path2D.Double();
path1.append(new Line2D.Double(76, 62, 31, 62 ),true);
path1.append(new Line2D.Double(31, 62, 31, 70.00000000000001 ),true);
path1.append(new Line2D.Double(31, 70.00000000000001, 76, 70 ),true);
Area area1 = new Area(path1);
Path2D.Double path2 = new Path2D.Double();
path2.append(new Line2D.Double(52, 10,52,130),true);
path2.append(new Line2D.Double(52, 130,60,130),true);
path2.append(new Line2D.Double(60, 130,60.0,10),true);
Area area2 = new Area(path2);
g.fill(area1);
g.setColor(Color.red);
g.fill(area2);
Area areaIntersect = new Area(path1);
areaIntersect.intersect(area2);
g.setColor(Color.yellow);
g.draw(areaIntersect);
PathIterator pi = areaIntersect.getPathIterator(null);
while(!pi.isDone())
{
double[] coords = new double[6];
switch(pi.currentSegment(coords))
{
case PathIterator.SEG_CLOSE:
break;
case PathIterator.SEG_CUBICTO:
System.out.println(coords[4] + "," + coords[5]);
case PathIterator.SEG_QUADTO:
System.out.println(coords[2] + "," + coords[3]);
case PathIterator.SEG_MOVETO:
case PathIterator.SEG_LINETO:
System.out.println(coords[0] + "," + coords[1]);
}
pi.next();
}
}
}
}
结果:
交叉点应该只是一个黄色方块;长的黄色水平线不应成为结果的一部分。
我知道问题与蓝色框底部的非常小的角度有关:
Line2D.Double(31,70.00000000000001,76,70)
。如果我将 70.00000000000001 更改为几乎任何其他值,交集框将正确显示。例如,将它们都更改为 70.000000000001:
path1.append(new Line2D.Double(31, 62, 31, 70.000000000001 ),true);
path1.append(new Line2D.Double(31, 70.000000000001, 76, 70 ),true);
我打印了生成的相交的坐标,以确保我看到的不是显示问题,但它清楚地显示了 x 轴上从 31.0 到 76.0 的线,而它应该只是 52.0 到 60.0。
52.0,60.0
52.0,70.00000000000001
31.0,70.00000000000001
76.0,70.0
60.0,70.0
60.0,60.0
我正在做一些三角学来生成多边形,因此预计会出现 0.00000000000001 这样的值。我可以将它们四舍五入,但在不知道是什么导致问题的情况下,我担心它可能会出现在其他值中。
首先,我删除了缩放,但这没有帮助。
接下来我将
closePath
添加到两条路径中,但这没有帮助。
接下来,我向每个路径添加一条附加行以确保路径正确关闭,但这没有帮助。
接下来我使用
Rectangle2D
代替 Path
并解决了问题。所以问题出在Path
s。
接下来,我更改了交集以使用预先存在的
Area
而不是第一个 Path
和第二个 Area
。
Area areaIntersect = new Area(area1);
areaIntersect.intersect(area2);
这没有帮助。
现在我正在摸不着头脑。我回去将
Path
与 Rectangle2D
进行比较,并注意到路径一“似乎”具有逆时针缠绕,因此我将其更改为顺时针缠绕......
Path2D.Double path1 = new Path2D.Double();
path1.append(new Line2D.Double(31, 62, 76, 62), true);
path1.append(new Line2D.Double(76, 62, 76, 70.00000000000001), true);
path1.append(new Line2D.Double(76, 70.00000000000001, 31, 70.00000000000001), true);
path1.append(new Line2D.Double(31, 70.00000000000001, 31, 62), true);
path1.closePath();
成功了!
70
和70.00000000000001
之间的差异也可能存在问题,尽管在我更新的测试中,它似乎没有什么区别。
为什么绕组很重要?在这种情况下,我不能说,但它似乎有所作为。
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.geom.Area;
import java.awt.geom.Line2D;
import java.awt.geom.Path2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame();
frame.setSize(400, 400);
frame.setLocationRelativeTo(null);
JPanel panel = new TestPane();
frame.add(panel);
frame.setVisible(true);
}
});
}
class TestPane extends JPanel {
TestPane() {
setBackground(new Color(0, 50, 0));
setFocusable(true);
}
@Override
public void paintComponent(Graphics g1) {
super.paintComponent(g1);
Graphics2D g = (Graphics2D) g1;
AffineTransform at = new AffineTransform();
at.scale(3, 3);
g.transform(at);
Path2D.Double path1 = new Path2D.Double();
path1.append(new Line2D.Double(31, 62, 76, 62), true);
path1.append(new Line2D.Double(76, 62, 76, 70.00000000000001), true);
path1.append(new Line2D.Double(76, 70.00000000000001, 31, 70.00000000000001), true);
path1.append(new Line2D.Double(31, 70, 31, 62), true);
path1.closePath();
Path2D.Double path2 = new Path2D.Double();
path2.append(new Line2D.Double(52, 10, 52, 130), true);
path2.append(new Line2D.Double(52, 130, 60, 130), true);
path2.append(new Line2D.Double(60, 130, 60.0, 10), true);
path2.append(new Line2D.Double(60.0, 10, 52, 10), true);
path2.closePath();
Area area1 = new Area(path1);
Area area2 = new Area(path2);
g.setColor(Color.blue);
g.draw(area1);
g.setColor(Color.red);
g.draw(area2);
Area areaIntersect = new Area(area1);
areaIntersect.intersect(area2);
g.setColor(Color.yellow);
g.draw(areaIntersect);
}
}
}