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. :)
I suggest you
- implement a ruler-drawing-method that draws a simple horizontal ruler from left to right
- Figure out the desired angle using
Math.atan2
.
- 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);
}
}
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.
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