我在Graphics上下文中绘制了一个java.awt.Shape并将其显示给用户。为了定位和调整图形上下文的大小,我使用了我创建的库中的形状边界。这适用于我生成的大多数形状。
问题是我的定位算法不适用于使用Arc2D.Float生成的形状。当使用这个类来生成形状时,我得到一个在其边界中具有负y坐标的形状。
我研究了很多,但找不到任何关于这个负y坐标含义的信息。如果我忽略坐标,我可以正确定位这个特定的形状,但仍然存在以下问题:
下面是一段演示此问题的源代码。尝试使用形状的y坐标进行平移的未修改代码会生成以下显示: 如果使用零y翻译在源代码中的g.translate()行中进行注释,则会显示以下内容: 似乎负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 );
}
} );
}
}
答案 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 );