5

AWT/Swingを使用してJavaで高精度の円弧を描画しようとしています。Graphicsクラスは、これを行うための「drawArc」メソッドを提供し、ほとんどの場合、これで問題ありません。ただし、円弧の半径が大きい場合(つまり、「幅」と「高さ」のパラメータが大きい場合)、円弧は正確に描画されません。これは、「startAngle」および「arcAngle」パラメーターが整数度として指定されているためです。角度(ラジアンで指定)を度に変換してから丸める必要があります。精度が低下すると、アークが実際の終点を下回ったり(切り捨てた場合)、本来よりも遠くに移動したりします(切り上げた場合)。

円弧を描く別の方法を探しています。これは同じように機能することが望ましいですが、浮動小数点の角度をパラメーターとして受け入れます。

そのような関数が存在しない場合(私はそれを見つけることができませんでした)私はそれを自分で書きたいのですが、Graphicsクラスはすでに私が見つけることができる最低レベルの描画メソッドを提供しているのでこれをどうやって行うのか分かりません。私が持っていた唯一のアイデアは、一連の直線で円弧を近似することですが、滑らかな円弧を取得するには、多くの線が必要になり、これは非常に非効率的です。

4

2 に答える 2

6

角度パラメータにdouble値を使用したい場合は、Arc2D.Doubleなどの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();
         }
      });
   }
}
于 2013-02-02T20:18:24.760 に答える
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);

そして、正確なシータ値に描画される1つの円弧があります。再描画のオーバーラップが少しあるため、マシン的にはおそらく最も効率的な方法ではありません。しかし、それは私が考えることができる最も簡単な方法です。

于 2017-12-07T19:03:10.987 に答える