使用Area.intersect()求多边形交集出现异常结果问题
使用Area.intersect()计算多边形交集时出现异常结果
问题概述
我尝试通过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(); } } } }
异常表现
运行代码后,黄色交集区域本应是一个矩形,但实际出现了多余的长线条。打印交集的坐标点后确认这不是渲染问题,结果中确实包含了超出正确范围的线段:
52.0,60.0 52.0,70.00000000000001 31.0,70.00000000000001 76.0,70.0 60.0,70.0 60.0,60.0
正确的交集范围应该是x轴52.0到60.0之间,但结果中出现了31.0到76.0的线段。
问题定位
经过测试,问题和蓝色矩形底部的微小浮点偏差有关:Line2D.Double(31,70.00000000000001,76,70)。当把70.00000000000001修改为其他近似值(比如70.000000000001)时,交集显示恢复正常。
由于我的多边形是通过三角函数生成的,这类极小的浮点误差是预期会出现的情况。虽然可以通过数值取整暂时解决,但不清楚问题的根本原因,担心其他类似浮点值场景下还会出现异常。
更新:尝试改进后的结果
参考相关方案修改了path1的路径定义,补充了闭合路径的代码:
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.0000000000001), true); path1.append(new Line2D.Double(76, 70.0000000000001, 31, 70), true); path1.append(new Line2D.Double(31, 70, 31, 62), true); path1.closePath();
修改后的结果有所改善,但仍未完全恢复正常,交集区域仍存在异常线条。
内容的提问来源于stack exchange,提问作者Joe
相关产品推荐
相关产品推荐

