我尝试使用AWT / Swing在Java中绘制高精度弧。 Graphics类提供" drawArc"这样做的方法,在大多数情况下这很好。但是,当弧具有较大的半径(即,"宽度""高度"参数较大)时,将不会精确绘制弧。这是因为" startAngle"和" arcAngle"参数以整数度给出。我被迫将一个角度(以弧度给出)转换为度数,然后将其四舍五入。精度的损失会导致电弧低于其实际终点(如果你向下舍入)或超出它应该的距离(如果你向上舍入)。
我正在寻找另一种绘制弧线的方法。最好这应该以相同的方式工作,但接受浮点角度作为参数。
如果这样的功能不存在(我找不到),我想自己写一下,但是我不知道如何解决这个问题,因为Graphics类已经提供了最低级别的功能我能找到的绘画方法。我唯一的想法就是用一系列直线来近似弧线,但为了获得平滑的弧线,你需要很多线条,这看起来非常低效。
答案 0 :(得分:5)
如果您希望对角度参数使用双精度值,为什么不使用Arc2D这样的Arc2D.Double对象?您提到的所有参数都是双重类型。
另外,您是否正确设置了Graphics2D对象的RenderingHints以允许消除锯齿?
例如,
import java.awt.*;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.geom.Arc2D;
import javax.swing.*;
@SuppressWarnings("serial")
public class TestArc2D extends JPanel {
private static final int PREF_W = 1000;
private static final int PREF_H = 400;
private static final Stroke STROKE = new BasicStroke(5f);
private static final Color ARC_COLOR = Color.red;
private Arc2D arc;
public TestArc2D() {
addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e) {
double x = 10;
double y = x;
double w = getWidth() - 2 * x;
double h = 2 * getHeight() - 2 * y - 50;
double start = 0;
double extent = 180.0;
arc = new Arc2D.Double(x, y, w, h, start , extent, Arc2D.OPEN);
}
});
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g.create();
g2.setStroke(STROKE);
g2.setColor(ARC_COLOR);
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
if (arc != null) {
g2.draw(arc);
}
g2.dispose();
}
@Override
public Dimension getPreferredSize() {
return new Dimension(PREF_W, PREF_H);
}
private static void createAndShowGui() {
TestArc2D mainPanel = new TestArc2D();
JFrame frame = new JFrame("TestArc2D");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
答案 1 :(得分:1)
使用Graphics2D,您可以使用rotate(theta,x,y)函数精确绘制弧的一端:
g2.rotate(-1*thetaStartRadians,xc,yc);
g2.drawArc(x1,y1,width,height,0, thetaLengthDegrees-1);
g2.rotate(thetaStartRadians,xc,yc);
然后你只需要精确地画出另一边的最后一点:
g2.rotate(-1*thetaLengthRadians,xc,yc);
g2.drawArc(x1,y1,width,height,0,-2));
g2.rotate(thetaLengthRadians,xc,yc);
并且您将有一个弧线绘制到精确的θ值。从机器方面来说,它可能不是最有效的方法,因为重绘重叠;但这是我能想到的最简单的方法。