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

时间:2010-08-15 17:22:34

标签: java swing graphics awt computational-geometry

我正在使用Java AWT在面板上绘制线条(Line2DGraphics2D.drawLine()),我想知道如何绘制带刻度线的线条,类似于:

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

我知道我想提前勾画的位置。

线条可以处于任何位置,因此必须以与线条本身相关的角度绘制刻度线。

我的基本几何图形和在Java中应用它的能力让我失望。 :)

3 个答案:

答案 0 :(得分:13)

我建议你

  1. 实现一个从左到右绘制简单水平标尺的标尺绘图方法
  2. 使用Math.atan2计算出所需的角度。
  3. 在调用ruler-drawing-method之前,应用AffineTransform进行平移和旋转。
  4. 这是一个完整的测试程序。 (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-calls将经历相同的转换,并沿着该线很好地“倾斜”。

答案 1 :(得分:1)

需要注意的事项:

  • 垂直线的斜率为-1 / oldslope。
  • 为了支持任何方向的线路,您需要参数化
  • 因此,你在原始行中有dy和dx,这意味着newdx=dy; newdy=-1*dx
  • 如果你有这样的<dx, dy>是一个单位向量(sqrt(dx*dx+dy+dy)==1,或dx==cos(theta); dy=sin(theta)对于某些theta),那么你只需要知道你想要多远的刻度线
  • sx,sy是你的开始x和y
  • length是行的长度
  • seglength是短划线的长度
  • dx,dy是原始线的斜率
  • newdx,newdy是交叉线的(上面计算的)斜率

因此,

  1. <sx,sy>(开始x,y)到<sx+dx*length,sy+dy*length>
  2. 画一条线
  3. 绘制一组行(for(i = 0; i&lt; = length; i + = interval)从<sx+dx*i-newdx*seglength/2,sy+dy*i-newdy*seglength/2><sx+dx*i+newdx*seglength/2,sy+dy*i+newdy*seglength/2>

答案 2 :(得分: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)

希望它有所帮助,
罗尼