You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 00:44:51