Java - 绘制标尺(在90度角刻有刻度线)

问题描述:

我正在使用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

我建议

  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的斜率/ 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

我希望你知道矩阵乘法。为了旋转一条线,你需要通过旋转矩阵来多重旋转一条线。 (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)就像你所期望的那样。

希望它能帮助,
罗尼