2010-08-15 75 views
7

我正在使用Java AWT在面板上繪製線條(Line2DGraphics2D.drawLine()),我想知道如何繪製刻度線,類似於:Java - 繪製標尺(在90度角刻有刻度線)

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

我知道我希望提前打勾的位置。

這些線可以在任何位置,所以蜱必須以與線本身相關的角度繪製。

我的基本幾何&在Java中應用它的能力讓我失望。 :)

+0

你想畫任意方向的「尺子」行?蜱是以固定的時間間隔出現,還是希望它們出現,例如0%,33%,66%,100%? – aioobe 2010-08-15 17:32:32

+0

請參閱下面有關圖形的一般說明。刻度線將以任意間距均勻間隔。 (IE:我需要一個解決方案,我可以將線劃分並在每個線段沿其長度繪製任意數量的這些刻度) – Matt 2010-08-15 17:40:13

+0

讓我知道您對我的答案的看法。 – jjnguy 2010-08-15 19:00:12

回答

13

我建議

  1. 你實現一個尺子拉法從左至右
  2. 圖出使用Math.atan2所需的角度,吸引了一個簡單的水平標尺。
  3. 在調用標尺繪圖方法之前,應用帶翻譯和旋轉的AffineTransform

這是一個完整的測試程序。 (該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); 
    } 
} 

enter image description here

注意,你可以很容易地得出的數字在蜱之上。 drawString調用將經歷相同的轉換,並沿着該線很好地「傾斜」。

+0

有趣的是,我相信'AffineTransform'是我一直在尋找的關鍵詞。 Google使用非常相似的組件製作了本教程: http://www.glyphic.com/transform/applet/1intro.html 現在我只需瞭解如何將其應用於我的問題。 – Matt 2010-08-15 17:43:34

+0

通過首先平移(移動)到所需起點,然後旋轉所需角度​​(atan2(dy,dx))來應用它。將兩個轉換與AffineTransform.concatenate結合在一起。 – aioobe 2010-08-15 19:26:15

+1

看起來不錯。我需要讓自己更熟悉Transform的東西。 – jjnguy 2010-08-15 19:30:27

1

事情需要指出的是:

  • 的垂線具有-1的斜率/ oldslope。
  • 爲了支持任何方向的線條,您需要以參數方式進行
  • 因此,您在原始線條上具有dy和dx,這意味着newdx=dy; newdy=-1*dx
  • 如果你有這樣的<dx, dy>是一個單位矢量(sqrt(dx*dx+dy+dy)==1dx==cos(theta); dy=sin(theta)爲某些theta),然後你只需要知道你想要多大的分隔符。
  • SX,SY是你開始x和y
  • 長度是線的長度
  • seglength是破折號的長度
  • DX,DY是原線
  • newdx的山坡上, newdy是交叉線

因此的(上文計算的)的斜率,

  1. 畫出一個從<sx,sy>線(啓動x,y)提供到<sx+dx*length,sy+dy*length>
  2. 畫出一組線(對於(I = 0;我< =長度; I + =間隔)從<sx+dx*i-newdx*seglength/2,sy+dy*i-newdy*seglength/2><sx+dx*i+newdx*seglength/2,sy+dy*i+newdy*seglength/2>
+0

我非常喜歡這個答案,因爲它試圖解釋幾何。不幸的是,我無法繞過它。我插入你描述的公式,我得到了newdy&newdx非常奇怪的結果。 (負值遠遠超出我面板上的座標範圍) 同樣,我的幾何圖形是最好的,但我想知道該公式是否爲笛卡爾座標系。Java的座標將0,0放置在面板的左上角。 – Matt 2010-08-15 18:30:04

1

我希望你知道矩陣乘法。爲了旋轉一條線,你需要通過旋轉矩陣來多重旋轉一條線。 (I coudln't繪製一個適當的矩陣,但假設這兩個線不分離)

|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)就像你所期望的那樣。

希望它能幫助,
羅尼