Sunday, May 30, 2004
兩點間畫有箭頭的線
不知道有沒有更好的作法~
//畫箭頭 double x1 = fromPoint.getX(); double y1 = fromPoint.getY(); double x2 = toPoint.getX(); double y2 = toPoint.getY(); double distance = fromPoint.distance(toPoint); double cita = Math.toDegrees(Math.asin(Math.abs(y1 - y2) / distance)); double subCitaSin = ARROW_LENGTH * Math.sin(Math.toRadians(cita - 30)); double subCitaCos = ARROW_LENGTH * Math.cos(Math.toRadians(cita - 30)); double addCitaSin = ARROW_LENGTH * Math.sin(Math.toRadians(cita + 30)); double addCitaCos = ARROW_LENGTH * Math.cos(Math.toRadians(cita + 30)); double up1, down1, up2, down2; if(x1 > x2){ //箭頭在第二象限 if(y1 > y2){ up1 = x2 + subCitaCos; down1 = y2 + subCitaSin; up2 = x2 + addCitaCos; down2 = y2 + addCitaSin; } //箭頭在第三象限 else{ up1 = x2 + subCitaCos; down1 = y2 - subCitaSin; up2 = x2 + addCitaCos; down2 = y2 - addCitaSin; } } else{ //箭頭在第一象限 if(y1 > y2){ up1 = x2 - subCitaCos; down1 = y2 + subCitaSin; up2 = x2 - addCitaCos; down2 = y2 + addCitaSin; } //箭頭在第四象限 else{ up1 = x2 - subCitaCos; down1 = y2 - subCitaSin; up2 = x2 - addCitaCos; down2 = y2 - addCitaSin; } } g2d.draw(new Line2D.Double(new Point2D.Double(up1, down1), toPoint)); g2d.draw(new Line2D.Double(new Point2D.Double(up2, down2), toPoint));由 swanky 發表於 May 30, 2004 11:56 PM
剛好路過, 覺得您的做法太繁瑣...
多多利用平移,旋轉將會讓您輕鬆許多.
野人獻曝,請多包含.
Here is my example:
import javax.swing.*;
import java.awt.*;
import java.awt.geom.*;
/**
* @author T55555
* @version 1.0.0 2004-06-30
*/
public class DrawArrow extends JComponent {
public static void main(String[] args) {
JFrame f = new JFrame("DrawArrow ----- by T55555");
f.getContentPane().add(new DrawArrow());
f.setSize(275, 150);
f.setLocationRelativeTo(null);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
public void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
double p = 10.0;
double q = 100.0;
double m = (p + q) / 2;
ciyawasay_drawArrow(g2d, new Point2D.Double(p, p), new Point2D.Double(q, q));
ciyawasay_drawArrow(g2d, new Point2D.Double(q, q), new Point2D.Double(p, p));
ciyawasay_drawArrow(g2d, new Point2D.Double(p, q), new Point2D.Double(q, p));
ciyawasay_drawArrow(g2d, new Point2D.Double(q, p), new Point2D.Double(p, q));
ciyawasay_drawArrow(g2d, new Point2D.Double(m, p), new Point2D.Double(m, q));
ciyawasay_drawArrow(g2d, new Point2D.Double(m, q), new Point2D.Double(m, p));
ciyawasay_drawArrow(g2d, new Point2D.Double(p, m), new Point2D.Double(q, m));
ciyawasay_drawArrow(g2d, new Point2D.Double(q, m), new Point2D.Double(p, m));
g2d.translate(150.0, 0.0);
t55555_drawArrow(g2d, new Point2D.Double(p, p), new Point2D.Double(q, q));
t55555_drawArrow(g2d, new Point2D.Double(q, q), new Point2D.Double(p, p));
t55555_drawArrow(g2d, new Point2D.Double(p, q), new Point2D.Double(q, p));
t55555_drawArrow(g2d, new Point2D.Double(q, p), new Point2D.Double(p, q));
t55555_drawArrow(g2d, new Point2D.Double(m, p), new Point2D.Double(m, q));
t55555_drawArrow(g2d, new Point2D.Double(m, q), new Point2D.Double(m, p));
t55555_drawArrow(g2d, new Point2D.Double(p, m), new Point2D.Double(q, m));
t55555_drawArrow(g2d, new Point2D.Double(q, m), new Point2D.Double(p, m));
g2d.translate(-150.0, 0.0);
}
public void ciyawasay_drawArrow(Graphics2D g2d, Point2D fromPoint, Point2D toPoint) {
double ARROW_LENGTH = 10.0;
double x1 = fromPoint.getX();
double y1 = fromPoint.getY();
double x2 = toPoint.getX();
double y2 = toPoint.getY();
double distance = fromPoint.distance(toPoint);
double cita = Math.toDegrees(Math.asin(Math.abs(y1 - y2) / distance));
double subCitaSin = ARROW_LENGTH * Math.sin(Math.toRadians(cita - 30));
double subCitaCos = ARROW_LENGTH * Math.cos(Math.toRadians(cita - 30));
double addCitaSin = ARROW_LENGTH * Math.sin(Math.toRadians(cita + 30));
double addCitaCos = ARROW_LENGTH * Math.cos(Math.toRadians(cita + 30));
double up1, down1, up2, down2;
if(x1 > x2){
if(y1 > y2){
up1 = x2 + subCitaCos;
down1 = y2 + subCitaSin;
up2 = x2 + addCitaCos;
down2 = y2 + addCitaSin;
}
else{
up1 = x2 + subCitaCos;
down1 = y2 - subCitaSin;
up2 = x2 + addCitaCos;
down2 = y2 - addCitaSin;
}
}
else{
if(y1 > y2){
up1 = x2 - subCitaCos;
down1 = y2 + subCitaSin;
up2 = x2 - addCitaCos;
down2 = y2 + addCitaSin;
}
else{
up1 = x2 - subCitaCos;
down1 = y2 - subCitaSin;
up2 = x2 - addCitaCos;
down2 = y2 - addCitaSin;
}
}
g2d.draw(new Line2D.Double(new Point2D.Double(up1, down1), toPoint));
g2d.draw(new Line2D.Double(new Point2D.Double(up2, down2), toPoint));
g2d.draw(new Line2D.Double(fromPoint, toPoint));
}
// Note: pre-condition: toPoint != fromPoint
// ( if the 2 points are the same ===> distance == 0 and angle is indeterminate )
public void t55555_drawArrow(Graphics2D g2d, Point2D fromPoint, Point2D toPoint) {
double ARROW_LENGTH = 10.0;
double ARROW_ANGLE = Math.toRadians(30);
double ax = ARROW_LENGTH * Math.cos(ARROW_ANGLE);
double ay = ARROW_LENGTH * Math.sin(ARROW_ANGLE);
AffineTransform originTransform = g2d.getTransform();
g2d.translate(toPoint.getX(), toPoint.getY());
g2d.rotate((fromPoint.getY() > toPoint.getY() ? -1 : 1) * Math.acos((toPoint.getX() - fromPoint.getX()) / fromPoint.distance(toPoint)));
g2d.draw(new Line2D.Double(0, 0, -ax, -ay));
g2d.draw(new Line2D.Double(0, 0, -ax, ay));
g2d.setTransform(originTransform);
g2d.draw(new Line2D.Double(fromPoint, toPoint));
}
}
The main idea is translate the origin to the toPoint,
and rotate to make the axe X parallel to the vector (fromPoint, toPoint).
For the rotate angle, the "classic" way is try to using atan like:
if (x1 > x2) {
g2d.rotate(Math.PI + Math.atan((y1 - y2) / (x1 - x2)));
} else if (x1 y2) {
g2d.rotate( -Math.PI / 2 );
} else if (y1
g2d.rotate( Math.PI / 2);
} else {
return;
}
As you can see, there are many checking to do.
The example I show you do not using the atan.
I am using vector dot product formula.
A . B = |A| |B| cos(theda)
with A = vector (fromPoint, toPoint),
B = (1, 0) (axe X, unit vector)
In case if you want fill the arrow, with
3rd point that can define by the distance from the toPoint, the method I used will even simpler(compare to yours).
Oops, it seems the atan checking have trouble to layout...
(my post code is not the same as showing on the page, bug on the post text re-formating ?)
Anyway, I do not know how to layout to post it correctly. And this is real simple algebra formula.
太感謝了~
您的方法真是比我的好很多~ ^^"