Java - 画一把尺子(带有90度角刻度线的线)

发布于 2024-09-14 14:04:23 字数 250 浏览 7 评论 0原文

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

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

我提前知道我想要绘制刻度线的位置。

这些线可以位于任何位置,因此必须以相对于线本身的角度绘制刻度。

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

I'm using Java AWT to draw lines on a panel (Line2D and Graphics2D.drawLine()) and I'm wondering how I can draw a line with tick marks, similar to:

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

I know the positions I'd like to draw the ticks at in advance.

The lines could be in any position, so the ticks must be drawn at an angle releative to the line itself.

My basic geometry & ability to apply it in Java is failing me. :)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

阪姬 2024-09-21 14:04:23

我建议您

  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);
    }
}

( net/zjZgf.png" alt="在此处输入图像描述">

请注意,您可以轻松地在刻度上方绘制数字。绘制字符串调用将经历相同的转换,并沿线很好地“倾斜”。

I suggest you

  1. implement a ruler-drawing-method that draws a simple horizontal ruler from left to right
  2. Figure out the desired angle using Math.atan2.
  3. Apply an AffineTransform with translation and rotation before invoking the ruler-drawing-method.

Here is a complete test-program. (The Graphics.create method is used to create a copy of the original graphics object, so we don't mess up the original transform.)

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

Note, that you could just as easily draw numbers above the ticks. The drawString-calls would go through the same transformation and get nicely "tilted" along the line.

泛泛之交 2024-09-21 14:04:23

需要注意的是:

  • 垂直线的斜率为-1/oldslope。
  • 为了支持任何方向的线,您需要以参数方式进行操作,
  • 因此,您有 dy 和 dx 穿过原始线,这意味着 newdx=dy; newdy=-1*dx。
  • 如果您的 是一个单位向量(sqrt(dx*dx+dy+dy)==1,或 dx ==cos(theta); dy=sin(theta) 对于某些 theta),您只需要知道您想要刻度线的距离。
  • sx, sy 是起点 x 和 y
  • length 是线的长度
  • seglength 是虚线的长度
  • dx, dy 是原始线的斜率
  • newdx, newdy 是交叉线的(上面计算的)斜率

因此,

  1. 绘制从 (开始 x,y)到
  2. 的一条线 绘制一组线( for(i=0;i<=length;i+=interval) 从

Things that need noting:

  • A perpendicular line has a slope of -1/oldslope.
  • In order to support lines in any direction, you need to do it parametrically
  • Thus, you have dy and dx across the original line, which means that newdx=dy; newdy=-1*dx.
  • If you have it such that <dx, dy> is a unit vector (sqrt(dx*dx+dy+dy)==1, or dx==cos(theta); dy=sin(theta) for some theta), you then just need to know how far apart you want the tick marks.
  • sx, sy are your start x and y
  • length is the length of the line
  • seglength is the length of the dashes
  • dx, dy is the slopes of the original line
  • newdx, newdy are the (calculated above) slopes of the cross lines

Thus,

  1. Draw a line from <sx,sy> (start x,y) to <sx+dx*length,sy+dy*length>
  2. Draw a set of lines (for(i=0;i<=length;i+=interval) from <sx+dx*i-newdx*seglength/2,sy+dy*i-newdy*seglength/2> to <sx+dx*i+newdx*seglength/2,sy+dy*i+newdy*seglength/2>
蓝色星空 2024-09-21 14:04:23

我希望你知道矩阵乘法。为了旋转一条线,您需要将其乘以旋转矩阵。 (我无法绘制正确的矩阵,但假设两条线都没有分开)

|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)预计。

希望有帮助,
罗尼

I hope you know matrix multiplication. In order to rotate a line you need to multiple it by rotation matrix. (I coudln't draw a proper matrix but assume both line are not separated)

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

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

The old points are x,y and the new is x',y'. Let us illustrate by an example, lets say you have a vertical line from (0,0) to (0,1), now you want to rotate it by 90 degrees. (0,0) will remain zero so lets just see what happens to (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|

you get to horizontal line (0,0),(0,1) like you would expect.

Hope it helps,
Roni

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文