7

私はJavaAWTを使用してパネル(Line2DおよびGraphics2D.drawLine())に線を描画していますが、次のような目盛り付きの線を描画するにはどうすればよいか疑問に思っています。

| ---- | ---- | ---- | ---- | ---- |

目盛りを描きたい位置を事前に知っています。

線は任意の位置に配置できるため、目盛りは線自体に対して相対的な角度で描画する必要があります。

私の基本的なジオメトリとJavaでそれを適用する能力は私を失敗させています。:)

4

3 に答える 3

12

私はあなたに提案します

  1. 単純な水平定規を左から右に描画する定規描画メソッドを実装します
  2. を使用して目的の角度を計算しMath.atan2ます。
  3. AffineTransformruler-drawing-methodを呼び出す前に、withtranslationとrotationを適用します。

これが完全なテストプログラムです。(このGraphics.createメソッドは、元のグラフィックスオブジェクトのコピーを作成するために使用されるため、元の変換を台無しにすることはありません。)

import java.awt.*;

public class RulerExample {

    public static void main(String args[]) {
        JFrame f = new JFrame();
        f.add(new JComponent() {

            private final double TICK_DIST = 20;

            void drawRuler(Graphics g1, int x1, int y1, int x2, int y2) {
                Graphics2D g = (Graphics2D) g1.create();

                double dx = x2 - x1, dy = y2 - y1;
                double len = Math.sqrt(dx*dx + dy*dy);
                AffineTransform at = AffineTransform.getTranslateInstance(x1, y1);
                at.concatenate(AffineTransform.getRotateInstance(Math.atan2(dy, dx)));
                g.transform(at);

                // Draw horizontal ruler starting in (0, 0)
                g.drawLine(0, 0, (int) len, 0);
                for (double i = 0; i < len; i += TICK_DIST)
                    g.drawLine((int) i, -3, (int) i, 3);
            }

            public void paintComponent(Graphics g) {
                drawRuler(g, 10, 30, 300, 150);
                drawRuler(g, 300, 150, 100, 100);
                drawRuler(g, 100, 100, 120, 350);
                drawRuler(g, 50, 350, 350, 50);
            }
        });

        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setSize(400, 400);
        f.setVisible(true);
    }
}

ここに画像の説明を入力してください

目盛りの上に同じように簡単に数字を描くことができることに注意してください。drawString-callsは同じ変換を経て、線に沿ってうまく「傾斜」します。

于 2010-08-15T17:39:05.837 に答える
1

注意が必要なこと:

  • 垂線の傾きは-1/oldslopeです。
  • あらゆる方向のラインをサポートするには、パラメトリックにそれを行う必要があります
  • したがって、元の行にdyとdxがあります。これは、を意味しnewdx=dy; newdy=-1*dxます。
  • <dx, dy>単位ベクトル(sqrt(dx*dx+dy+dy)==1、または一部のシータの場合)であるようなものがあるdx==cos(theta); dy=sin(theta)場合は、目盛りがどれだけ離れているかを知る必要があります。
  • sx、syはあなたのスタートxとyです
  • 長さは線の長さです
  • seglengthはダッシュの長さです
  • dx、dyは元の線の傾きです
  • newdx、newdyは、クロスラインの(上記で計算された)勾配です。

したがって、

  1. <sx,sy>(start x、y)からに線を引きます<sx+dx*length,sy+dy*length>
  2. <sx+dx*i-newdx*seglength/2,sy+dy*i-newdy*seglength/2>からの線のセットを描画します(for(i = 0; i <= length; i + = interval)<sx+dx*i+newdx*seglength/2,sy+dy*i+newdy*seglength/2>
于 2010-08-15T17:51:13.727 に答える
1

行列の掛け算を知っていることを願っています。ラインを回転させるには、回転行列で乗算する必要があります。(適切な行列を描くことができませんでしたが、両方の線が分離されていないと仮定します)

|x'| = |cos(an) -sin(an)| |x|

|y`| = |sin(an)  cos(an)| |y|

古い点は x,y で、新しい点は x',y' です。例で説明しましょう。(0,0) から (0,1) への垂直線があり、それを 90 度回転させたいとします。(0,0) はゼロのままなので、(0,1) に何が起こるか見てみましょう

|x'| = |cos(90) -sin(90)| |0|

|y`| = |sin(90)  cos(90)| |1|

==

|1 0| |0|

|0 1| |1|

==

| 1*0 + 0*1|

| 0*0 + 1*1|

== |0|

   |1|

(0,0),(0,1)期待どおりに水平線に到達します。

役に立てば幸いです、
ロニ

于 2010-08-15T18:50:55.283 に答える