001: import java.awt.geom.Point2D;
002: import java.awt.geom.Rectangle2D;
003: import java.util.ArrayList;
004:
005: /**
006: A style for a segmented line that indicates the number
007: and sequence of bends.
008: */
009: public class BentStyle extends SerializableEnumeration
010: {
011: private BentStyle() {}
012:
013: /**
014: Gets the points at which a line joining two rectangles
015: is bent according to this bent style.
016: @param start the starting rectangle
017: @param end the ending rectangle
018: @return an array list of points at which to bend the
019: segmented line joining the two rectangles
020: */
021: public ArrayList getPath(Rectangle2D start, Rectangle2D end)
022: {
023: ArrayList r = getPath(this, start, end);
024: if (r != null) return r;
025:
026: if (this == HVH) r = getPath(VHV, start, end);
027: else if (this == VHV) r = getPath(HVH, start, end);
028: else if (this == HV) r = getPath(VH, start, end);
029: else if (this == VH) r = getPath(HV, start, end);
030: if (r != null) return r;
031:
032: return getPath(STRAIGHT, start, end);
033: }
034:
035: /**
036: Gets the four connecting points at which a bent line
037: connects to a rectangle.
038: */
039: private static Point2D[] connectionPoints(Rectangle2D r)
040: {
041: Point2D[] a = new Point2D[4];
042: a[0] = new Point2D.Double(r.getX(), r.getCenterY());
043: a[1] = new Point2D.Double(r.getMaxX(), r.getCenterY());
044: a[2] = new Point2D.Double(r.getCenterX(), r.getY());
045: a[3] = new Point2D.Double(r.getCenterX(), r.getMaxY());
046: return a;
047: }
048:
049: /**
050: Gets the points at which a line joining two rectangles
051: is bent according to a bent style.
052: @param start the starting rectangle
053: @param end the ending rectangle
054: @return an array list of points at which to bend the
055: segmented line joining the two rectangles
056: */
057: private static ArrayList getPath(BentStyle bent,
058: Rectangle2D s, Rectangle2D e)
059: {
060: ArrayList r = new ArrayList();
061: if (bent == STRAIGHT)
062: {
063: Point2D[] a = connectionPoints(s);
064: Point2D[] b = connectionPoints(e);
065: Point2D p = a[0];
066: Point2D q = b[0];
067: double distance = p.distance(q);
068: for (int i = 0; i < a.length; i++)
069: for (int j = 0; j < b.length; j++)
070: {
071: double d = a[i].distance(b[j]);
072: if (d < distance)
073: {
074: p = a[i]; q = b[j];
075: distance = d;
076: }
077: }
078: r.add(p);
079: r.add(q);
080: }
081: else if (bent == HV)
082: {
083: double x1;
084: double x2 = e.getCenterX();
085: double y1 = s.getCenterY();
086: double y2;
087: if (x2 + MIN_SEGMENT <= s.getX())
088: x1 = s.getX();
089: else if (x2 - MIN_SEGMENT >= s.getMaxX())
090: x1 = s.getMaxX();
091: else return null;
092: if (y1 + MIN_SEGMENT <= e.getY())
093: y2 = e.getY();
094: else if (y1 - MIN_SEGMENT >= e.getMaxY())
095: y2 = e.getMaxY();
096: else return null;
097: r.add(new Point2D.Double(x1, y1));
098: r.add(new Point2D.Double(x2, y1));
099: r.add(new Point2D.Double(x2, y2));
100: }
101: else if (bent == VH)
102: {
103: double x1 = s.getCenterX();
104: double x2;
105: double y1;
106: double y2 = e.getCenterY();
107: if (x1 + MIN_SEGMENT <= e.getX())
108: x2 = e.getX();
109: else if (x1 - MIN_SEGMENT >= e.getMaxX())
110: x2 = e.getMaxX();
111: else return null;
112: if (y2 + MIN_SEGMENT <= s.getY())
113: y1 = s.getY();
114: else if (y2 - MIN_SEGMENT >= s.getMaxY())
115: y1 = s.getMaxY();
116: else return null;
117: r.add(new Point2D.Double(x1, y1));
118: r.add(new Point2D.Double(x1, y2));
119: r.add(new Point2D.Double(x2, y2));
120: }
121: else if (bent == HVH)
122: {
123: double x1;
124: double x2;
125: double y1 = s.getCenterY();
126: double y2 = e.getCenterY();
127: if (s.getMaxX() + 2 * MIN_SEGMENT <= e.getX())
128: {
129: x1 = s.getMaxX();
130: x2 = e.getX();
131: }
132: else if (e.getMaxX() + 2 * MIN_SEGMENT <= s.getX())
133: {
134: x1 = s.getX();
135: x2 = e.getMaxX();
136: }
137: else return null;
138: if (Math.abs(y1 - y2) <= MIN_SEGMENT)
139: {
140: r.add(new Point2D.Double(x1, (y1 + y2) / 2));
141: r.add(new Point2D.Double(x2, (y1 + y2) / 2));
142: }
143: else
144: {
145: r.add(new Point2D.Double(x1, y1));
146: r.add(new Point2D.Double((x1 + x2) / 2, y1));
147: r.add(new Point2D.Double((x1 + x2) / 2, y2));
148: r.add(new Point2D.Double(x2, y2));
149: }
150: }
151: else if (bent == VHV)
152: {
153: double x1 = s.getCenterX();
154: double x2 = e.getCenterX();
155: double y1;
156: double y2;
157: if (s.getMaxY() + 2 * MIN_SEGMENT <= e.getY())
158: {
159: y1 = s.getMaxY();
160: y2 = e.getY();
161: }
162: else if (e.getMaxY() + 2 * MIN_SEGMENT <= s.getY())
163: {
164: y1 = s.getY();
165: y2 = e.getMaxY();
166:
167: }
168: else return null;
169: if (Math.abs(x1 - x2) <= MIN_SEGMENT)
170: {
171: r.add(new Point2D.Double((x1 + x2) / 2, y1));
172: r.add(new Point2D.Double((x1 + x2) / 2, y2));
173: }
174: else
175: {
176: r.add(new Point2D.Double(x1, y1));
177: r.add(new Point2D.Double(x1, (y1 + y2) / 2));
178: r.add(new Point2D.Double(x2, (y1 + y2) / 2));
179: r.add(new Point2D.Double(x2, y2));
180: }
181: }
182: else return null;
183: return r;
184: }
185:
186: private static final int MIN_SEGMENT = 10;
187:
188: public static final BentStyle STRAIGHT = new BentStyle();
189: public static final BentStyle HV = new BentStyle();
190: public static final BentStyle VH = new BentStyle();
191: public static final BentStyle HVH = new BentStyle();
192: public static final BentStyle VHV = new BentStyle();
193: }