使用Arc2D

时间:2016-02-09 20:45:52

标签: java swing java-2d

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

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

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

  • 负y坐标是什么意思,一般应如何处理?
  • 负坐标如何与绑定的高度相关?

下面是一段演示此问题的源代码。尝试使用形状的y坐标进行平移的未修改代码会生成以下显示: Bad positioning, using negative y-bounds information, note the gap at the top of the image display 如果使用零y翻译在源代码中的g.translate()行中进行注释,则会显示以下内容: Gap shown now at the bottom, bounds information silently ignored 似乎负y需要从边界的高度中减去。这只强调我似乎错过了一些基本的理解......

我发现的唯一其他信息是,当使用启动它的Arc的其他开始和结束角度时,这根本不是问题。起始角度为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 );
            }
        } );
    }
}

1 个答案:

答案 0 :(得分:2)

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

  

请注意,无法保证返回的Rectangle2D是包含Shape的最小边界框,只是Shape完全位于指定的Rectangle2D内。

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

我不知道是否有正确的方法可以获得任意形状的真实边界。我的直觉是使用一个扁平的PathIterator,它保证只包含moveTo,lineTo和close操作:

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 );