Java Graphics2D正在关闭一个像素(舍入错误?) [英] Java Graphics2D is Drawing One Pixel Off (Rounding error?)
问题描述
我一直在尝试使用Graphics2D和PaintComponent在Java中创建程序。但是,Java没有正确地舍入一些值,导致一些点被渲染成与它应该给出不洁图像的位置不同的像素。你可以在下面的图片中看到我的意思。
这是我的代码。我可以改变什么来解决这个问题?谢谢!
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.setColor(Color.red);
int orginX = getWidth()/ 2;
int orginY = getHeight()/ 2;
for(int i = 0; i< = 360; i + = 10)
{
double angle = Math.toRadians(i);
double centerX = radius * Math.cos(angle)+ orginX;
double centerY = radius * Math.sin(angle)+ orginY;
int [] anglePointsX = {(int)(radius * Math.cos(angle + Math.toRadians(60))+ centerX),(int)(radius * Math.cos(angle-Math.toRadians(60) ))+ centerX),orginX};
int [] anglePointsY = {(int)(radius * Math.sin(angle + Math.toRadians(60))+ centerY),(int)(radius * Math.sin(angle-Math.toRadians(60) ))+ centerY),orginY};
g.drawPolygon(anglePointsX,anglePointsY,3);
}
尝试使用 i< 360
而不是 i< = 360
,因为你已经在这个角度画了一条线(0 == 360)
尝试使用 Path2D
或 GeneralPath
而不是 drawPolygon
因为这会给你 float
和 double
精确度
查看
然后我使用<$ c $更改了绘图c> drawPolygon 使用 Shape
API,特别是 Path2D
@Override
protected void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2d =(Graphics2D)g.create();
g2d.setColor(Color.red);
g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION,RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING,RenderingHints.VALUE_COLOR_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_DITHERING,RenderingHints.VALUE_DITHER_ENABLE);
g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,RenderingHints.VALUE_FRACTIONALMETRICS_ON);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION,RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING,RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,RenderingHints.VALUE_STROKE_PURE);
int orginX = getWidth()/ 2;
int orginY = getHeight()/ 2;
int dif =(int)(360 / 6d);
for(int i = 0; i< 360; i + = dif){
double angle = Math.toRadians(i);
double centerX = radius * Math.cos(angle)+ orginX;
double centerY = radius * Math.sin(angle)+ orginY;
Path2D path = new Path2D.Double();
path.moveTo(radius * Math.cos(angle + Math.toRadians(60))+ centerX,radius * Math.sin(angle + Math.toRadians(60))+ centerY);
path.lineTo((radius * Math.cos(angle - Math.toRadians(60))+ centerX),(radius * Math.sin(angle - Math.toRadians(60))+ centerY));
path.lineTo(orginX,orginY);
g2d.draw(路径);
}
g2d.dispose();
}
有和没有呈现提示
尽管如此,即使没有提示提示,问题也就消失了
I have been trying to make a program in Java using Graphics2D and PaintComponent. However, Java is not rounding some values correctly resulting in a few points being rendered a pixel different from where it supposed to be which gives an unclean image. You can see what I mean in the picture below.
Here is my code. What can I change to fix this? Thank you!
public void paintComponent( Graphics g )
{
super.paintComponent( g );
g.setColor(Color.red);
int orginX = getWidth()/2;
int orginY = getHeight()/2;
for(int i=0; i<=360; i+= 10)
{
double angle = Math.toRadians(i);
double centerX = radius * Math.cos(angle) + orginX;
double centerY = radius * Math.sin(angle) + orginY;
int[] anglePointsX = {(int) (radius * Math.cos(angle+Math.toRadians(60)) + centerX), (int) (radius * Math.cos(angle-Math.toRadians(60)) + centerX), orginX};
int[] anglePointsY = {(int) (radius * Math.sin(angle+Math.toRadians(60)) + centerY), (int) (radius * Math.sin(angle-Math.toRadians(60)) + centerY), orginY};
g.drawPolygon(anglePointsX, anglePointsY, 3);
}
Try using i < 360
instead i<=360
, as you've already drawen a line at this angle (0 == 360)
Try using a Path2D
or GeneralPath
rather then drawPolygon
as this will give you float
and double
precision
Have a look at Drawing Arbitrary Shapes for more details
Updated...
So I changed i <= 360
to i < 360
and didn't see any immediate changes, however, then applied some rendering hints and it seemed to improve the problem.
I started by reducing the number of elements to 6 (this is where I started seeing an issue) with
int dif = (int) (360 / 6d);
for (int i = 0; i < 360; i += dif) {
Then I applied some rendering hints...
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(Color.red);
g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
int orginX = getWidth() / 2;
int orginY = getHeight() / 2;
int dif = (int) (360 / 6d);
for (int i = 0; i < 360; i += dif) {
double angle = Math.toRadians(i);
double centerX = radius * Math.cos(angle) + orginX;
double centerY = radius * Math.sin(angle) + orginY;
int[] anglePointsX = {(int) (radius * Math.cos(angle + Math.toRadians(60)) + centerX), (int) (radius * Math.cos(angle - Math.toRadians(60)) + centerX), orginX};
int[] anglePointsY = {(int) (radius * Math.sin(angle + Math.toRadians(60)) + centerY), (int) (radius * Math.sin(angle - Math.toRadians(60)) + centerY), orginY};
g2d.drawPolygon(anglePointsX, anglePointsY, 3);
}
g2d.dispose();
}
Before and after comparison...
I then changed the drawing from using drawPolygon
to use the Shape
API, in particular a Path2D
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(Color.red);
g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
int orginX = getWidth() / 2;
int orginY = getHeight() / 2;
int dif = (int) (360 / 6d);
for (int i = 0; i < 360; i += dif) {
double angle = Math.toRadians(i);
double centerX = radius * Math.cos(angle) + orginX;
double centerY = radius * Math.sin(angle) + orginY;
Path2D path = new Path2D.Double();
path.moveTo(radius * Math.cos(angle + Math.toRadians(60)) + centerX, radius * Math.sin(angle + Math.toRadians(60)) + centerY);
path.lineTo((radius * Math.cos(angle - Math.toRadians(60)) + centerX), (radius * Math.sin(angle - Math.toRadians(60)) + centerY));
path.lineTo(orginX, orginY);
g2d.draw(path);
}
g2d.dispose();
}
With and without rendering hints
As you can, even without rendering hints, the issue is gone
这篇关于Java Graphics2D正在关闭一个像素(舍入错误?)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!