使用 Arc2D 创建的 java.awt.Shape 中负边界坐标的含义

Meaning of negative bounds coordinates in a java.awt.Shape created using Arc2D

我在图形上下文中绘制 java.awt.Shape 并将其显示给用户。为了定位和调整图形上下文的大小,我使用了我创建的库中的形状边界。这适用于我生成的大多数形状。

问题是我的定位算法不适用于使用 Arc2D.Float 生成的形状。当使用此 class 生成形状时,我得到一个在其边界内具有负 y 坐标的形状。

我研究了很多,但找不到任何关于这个负 y 坐标含义的信息。如果我忽略坐标,我可以正确定位这个特定的形状,但仍然存在以下问题:

下面是一段演示该问题的源代码。尝试使用形状的 y 坐标进行平移的未修改代码生成以下显示: 如果使用零 y 翻译在源代码的 g.translate() 行中注释,将显示以下内容: 似乎需要从边界的高度中减去负 y。这只是强调我似乎错过了一些基本的理解......

我发现的唯一其他信息是,当对开始这一切的弧使用其他开始和结束角度时,这根本不是问题。起始角度为 0,弧度为 45 度,一切正常。所以也有可能这是某个数学问题

希望有人能给个解释...

public class ShapeAnomaly
{
    public static void main( String[] argv ) throws Exception
    {
        //
        // Create the shape.
        //
        Shape shape = null;
        {
            Rectangle arcBounds = new Rectangle( 0, 0, 500, 500 );

            Path2D gp = new Path2D.Float();
            gp.append( new Arc2D.Float( arcBounds,
                        22.5f,
                        90.0f,
                        Arc2D.OPEN ), true );
            gp.closePath();

            shape = gp;
        }

        //
        // Create an image and paint the shape.
        //
        final Image image;
        {
            Rectangle2D bounds = shape.getBounds2D();
            System.err.println( "Bounds: " + bounds );

            BufferedImage bImage = new BufferedImage(
                    (int)bounds.getWidth(),
                    (int)bounds.getHeight(),
                    BufferedImage.TYPE_INT_ARGB );

            Graphics2D g = bImage.createGraphics();

            if ( bounds.getY() < 0 )
                System.err.println( "Anomaly..." );

            //
            // What is the correct handling of the bounds y-coordinate when
            // drawing the shape?
            // Should work, thought I know why, but doesn't.
            g.translate( -bounds.getX(), -bounds.getY() );
            // Works, but dunno why?
            //g.translate( -bounds.getX(), 0 ); 

            g.fill( shape );
            g.dispose();
            image = bImage;
        }

        //
        // Show the image in a window.
        //
        SwingUtilities.invokeLater( new Runnable()
        {
            @Override
            public void run()
            {
                JFrame frame = new JFrame( "Shape anomaly..." );
                frame.getContentPane().add( new JLabel( new ImageIcon( image ) ) );
                frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
                frame.pack();

                frame.setVisible( true );
            }
        } );
    }
}

来自documentation for the getBounds2D() method of Path2D.Float

Note that there is no guarantee that the returned Rectangle2D is the smallest bounding box that encloses the Shape, only that the Shape lies entirely within the indicated Rectangle2D.

这实际上只是 general contract of Shape.getBounds2D() 的副本。

我不知道是否有正确的方法来获取任意 Shape 的真实边界。我的直觉是使用扁平化的 PathIterator,它保证只包含 moveTo、lineTo 和关闭操作:

Rectangle2D bounds = null;
float[] coords = new float[6];
for (PathIterator i = shape.getPathIterator(null, 1);
     !i.isDone();
     i.next()) {

    if (i.currentSegment(coords) != PathIterator.SEG_CLOSE) {
        float x = coords[0];
        float y = coords[1];
        if (bounds == null) {
            bounds = new Rectangle2D.Float(x, y, 0, 0);
        } else {
            bounds.add(x, y);
        }
    }
}
System.err.println( "Bounds: " + bounds );