Java - 绘制标尺(在90度角刻有刻度线)
我正在使用Java AWT在面板上绘制线条(Line2D
和Graphics2D.drawLine()
),我想知道如何绘制刻度线,类似于:Java - 绘制标尺(在90度角刻有刻度线)
| ---- | ---- | ---- | ---- | ---- |
我知道我希望提前打勾的位置。
这些线可以在任何位置,所以蜱必须以与线本身相关的角度绘制。
我的基本几何&在Java中应用它的能力让我失望。 :)
我建议
- 你实现一个尺子拉法从左至右
- 图出使用
Math.atan2
所需的角度,吸引了一个简单的水平标尺。 - 在调用标尺绘图方法之前,应用带翻译和旋转的
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);
}
}
注意,你可以很容易地得出的数字在蜱之上。 drawString调用将经历相同的转换,并沿着该线很好地“倾斜”。
有趣的是,我相信'AffineTransform'是我一直在寻找的关键词。 Google使用非常相似的组件制作了本教程: http://www.glyphic.com/transform/applet/1intro.html 现在我只需了解如何将其应用于我的问题。 – Matt 2010-08-15 17:43:34
通过首先平移(移动)到所需起点,然后旋转所需角度(atan2(dy,dx))来应用它。将两个转换与AffineTransform.concatenate结合在一起。 – aioobe 2010-08-15 19:26:15
看起来不错。我需要让自己更熟悉Transform的东西。 – jjnguy 2010-08-15 19:30:27
事情需要指出的是:
- 的垂线具有-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
- 长度是线的长度
- seglength是破折号的长度
- DX,DY是原线
- newdx的山坡上, newdy是交叉线
因此的(上文计算的)的斜率,
- 画出一个从
<sx,sy>
线(启动x,y)提供到<sx+dx*length,sy+dy*length>
- 画出一组线(对于(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>
我非常喜欢这个答案,因为它试图解释几何。不幸的是,我无法绕过它。我插入你描述的公式,我得到了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)
就像你所期望的那样。
希望它能帮助,
罗尼
你想画任意方向的“尺子”行?蜱是以固定的时间间隔出现,还是希望它们出现,例如0%,33%,66%,100%? – aioobe 2010-08-15 17:32:32
请参阅下面有关图形的一般说明。刻度线将以任意间距均匀间隔。 (IE:我需要一个解决方案,我可以将线划分并在每个线段沿其长度绘制任意数量的这些刻度) – Matt 2010-08-15 17:40:13
让我知道您对我的答案的看法。 – jjnguy 2010-08-15 19:00:12