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: }