01: import java.awt.Color;
02: import java.awt.Graphics2D;
03: import java.awt.geom.GeneralPath;
04: import java.awt.geom.Point2D;
05: 
06: /**
07:    This class defines arrowheads of various shapes.
08: */
09: public class ArrowHead extends SerializableEnumeration
10: {
11:    private ArrowHead() {}
12:    /**
13:       Draws the arrowhead.
14:       @param g2 the graphics context
15:       @param p a point on the axis of the arrow head
16:       @param q the end point of the arrow head
17:    */
18:    public void draw(Graphics2D g2, Point2D p, Point2D q)
19:    {
20:       if (this == NONE) return;
21:       final double ARROW_ANGLE = Math.PI / 6;
22:       final double ARROW_LENGTH = 8;
23: 
24:       double dx = q.getX() - p.getX();
25:       double dy = q.getY() - p.getY();
26:       double angle = Math.atan2(dy, dx);
27:       double x1 = q.getX() 
28:          - ARROW_LENGTH * Math.cos(angle - ARROW_ANGLE);
29:       double y1 = q.getY() 
30:          - ARROW_LENGTH * Math.sin(angle - ARROW_ANGLE);
31:       double x2 = q.getX() 
32:          - ARROW_LENGTH * Math.cos(angle + ARROW_ANGLE);
33:       double y2 = q.getY() 
34:          - ARROW_LENGTH * Math.sin(angle + ARROW_ANGLE);
35: 
36:       GeneralPath path = new GeneralPath();
37:       path.moveTo((float) q.getX(), (float) q.getY());
38:       path.lineTo((float) x1, (float) y1);
39:       if (this == V)
40:       {
41:          path.moveTo((float) x2, (float) y2);
42:          path.lineTo((float) q.getX(), (float) q.getY());
43:       }
44:       else if (this == TRIANGLE)
45:       {
46:          path.lineTo((float) x2, (float) y2);
47:          path.closePath();                  
48:       }
49:       else if (this == DIAMOND || this == BLACK_DIAMOND)
50:       {
51:          double x3 = x1 - ARROW_LENGTH * Math.cos(angle + ARROW_ANGLE);
52:          double y3 = y1 - ARROW_LENGTH * Math.sin(angle + ARROW_ANGLE);
53:          path.lineTo((float) x3, (float) y3);
54:          path.lineTo((float) x2, (float) y2);
55:          path.closePath();         
56:       }
57:       Color oldColor = g2.getColor();
58:       if (this == BLACK_DIAMOND)
59:          g2.setColor(Color.BLACK);
60:       else
61:          g2.setColor(Color.WHITE);
62:       g2.fill(path);
63:       g2.setColor(oldColor);
64:       g2.draw(path);
65:    }
66: 
67:    public static final ArrowHead NONE = new ArrowHead();
68:    public static final ArrowHead TRIANGLE = new ArrowHead();
69:    public static final ArrowHead V = new ArrowHead();
70:    public static final ArrowHead DIAMOND = new ArrowHead();
71:    public static final ArrowHead BLACK_DIAMOND = new ArrowHead();
72: }