1: import java.awt.Graphics2D;
2: import java.awt.geom.Point2D;
3: import java.awt.geom.Rectangle2D;
4: import java.awt.geom.RectangularShape;
5: import java.io.IOException;
6: import java.io.ObjectInputStream;
7: import java.io.ObjectOutputStream;
9: /**
10: A node that has a rectangular shape.
11: */
12: public abstract class RectangularNode implements Node
13: {
14: public Object clone()
15: {
16: try
17: {
18: RectangularNode cloned = (RectangularNode) super.clone();
19: cloned.bounds = (Rectangle2D) bounds.clone();
20: return cloned;
21: }
22: catch (CloneNotSupportedException exception)
23: {
24: return null;
25: }
26: }
28: public void translate(double dx, double dy)
29: {
30: bounds.setFrame(bounds.getX() + dx,
31: bounds.getY() + dy,
32: bounds.getWidth(),
33: bounds.getHeight());
34: }
36: public boolean contains(Point2D p)
37: {
38: return bounds.contains(p);
39: }
41: public Rectangle2D getBounds()
42: {
43: return (Rectangle2D) bounds.clone();
44: }
46: public void setBounds(Rectangle2D newBounds)
47: {
48: bounds = newBounds;
49: }
51: public Point2D getConnectionPoint(Point2D aPoint)
52: {
53: double slope = bounds.getHeight() / bounds.getWidth();
54: double x = bounds.getCenterX();
55: double y = bounds.getCenterY();
56: double ex = aPoint.getX() - x;
57: double ey = aPoint.getY() - y;
58:
59: if (ex != 0 && -slope <= ey / ex && ey / ex <= slope)
60: {
61: // intersects at left or right boundary
62: if (ex > 0)
63: {
64: x = bounds.getMaxX();
65: y += (bounds.getWidth() / 2) * ey / ex;
66: }
67: else
68: {
69: x = bounds.getX();
70: y -= (bounds.getWidth() / 2) * ey / ex;
71: }
72: }
73: else if (ey != 0)
74: {
75: // intersects at top or bottom
76: if (ey > 0)
77: {
78: x += (bounds.getHeight() / 2) * ex / ey;
79: y = bounds.getMaxY();
80: }
81: else
82: {
83: x -= (bounds.getHeight() / 2) * ex / ey;
84: y = bounds.getY();
85: }
86: }
87: return new Point2D.Double(x, y);
88: }
90: private void writeObject(ObjectOutputStream out)
91: throws IOException
92: {
93: out.defaultWriteObject();
94: writeRectangularShape(out, bounds);
95: }
97: /**
98: A helper method to overcome the problem that the 2D shapes
99: aren't serializable. It writes x, y, width and height
100: to the stream.
101: @param out the stream
102: @param s the shape
103: */
104: private static void writeRectangularShape(
105: ObjectOutputStream out,
106: RectangularShape s)
107: throws IOException
108: {
109: out.writeDouble(s.getX());
110: out.writeDouble(s.getY());
111: out.writeDouble(s.getWidth());
112: out.writeDouble(s.getHeight());
113: }
115: private void readObject(ObjectInputStream in)
116: throws IOException, ClassNotFoundException
117: {
118: in.defaultReadObject();
119: bounds = new Rectangle2D.Double();
120: readRectangularShape(in, bounds);
121: }
122:
123: /**
124: A helper method to overcome the problem that the 2D shapes
125: aren't serializable. It reads x, y, width and height
126: from the stream.
127: @param in the stream
128: @param s the shape whose frame is set from the stream values
129: */
130: private static void readRectangularShape(ObjectInputStream in,
131: RectangularShape s)
132: throws IOException
133: {
134: double x = in.readDouble();
135: double y = in.readDouble();
136: double width = in.readDouble();
137: double height = in.readDouble();
138: s.setFrame(x, y, width, height);
139: }
141: private transient Rectangle2D bounds;
142: }