Area.intersect() 的意外结果

问题描述 投票:0回答:1

我试图通过

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 这样的值。我可以将它们四舍五入,但在不知道是什么导致问题的情况下,我担心它可能会出现在其他值中。

java awt graphics2d
1个回答
0
投票

首先,我删除了缩放,但这没有帮助。

接下来我将

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);
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.