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 enum BentStyle
010: {
011:    STRAIGHT, HV, VH, HVH, VHV;
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<Point2D> getPath(Rectangle2D start, Rectangle2D end)
022:    {
023:       ArrayList<Point2D> 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<Point2D> getPath(BentStyle bent,
058:       Rectangle2D s, Rectangle2D e)
059:    {
060:       ArrayList<Point2D> r = new ArrayList<Point2D>();
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 (Point2D point1 : a)
070:             //for (int j = 0; j < b.length; j++)
071:             for (Point2D point2 : b)
072:             {
073:                double d = point1.distance(point2);
074:                if (d < distance)
075:                {
076:                   p = point1; q = point2;
077:                   distance = d;
078:                }
079:             }
080:          r.add(p);
081:          r.add(q);
082:       }
083:       else if (bent == HV)
084:       {
085:          double x1;
086:          double x2 = e.getCenterX();
087:          double y1 = s.getCenterY();
088:          double y2;
089:          if (x2 + MIN_SEGMENT <= s.getX())
090:             x1 = s.getX();
091:          else if (x2 - MIN_SEGMENT >= s.getMaxX())
092:             x1 = s.getMaxX();
093:          else return null;
094:          if (y1 + MIN_SEGMENT <= e.getY())
095:             y2 = e.getY();
096:          else if (y1 - MIN_SEGMENT >= e.getMaxY())
097:             y2 = e.getMaxY();
098:          else return null;
099:          r.add(new Point2D.Double(x1, y1));
100:          r.add(new Point2D.Double(x2, y1));
101:          r.add(new Point2D.Double(x2, y2));
102:       }
103:       else if (bent == VH)
104:       {
105:          double x1 = s.getCenterX();
106:          double x2;
107:          double y1;
108:          double y2 = e.getCenterY();
109:          if (x1 + MIN_SEGMENT <= e.getX())
110:             x2 = e.getX();
111:          else if (x1 - MIN_SEGMENT >= e.getMaxX())
112:             x2 = e.getMaxX();
113:          else return null;
114:          if (y2 + MIN_SEGMENT <= s.getY())
115:             y1 = s.getY();
116:          else if (y2 - MIN_SEGMENT >= s.getMaxY())
117:             y1 = s.getMaxY();
118:          else return null;
119:          r.add(new Point2D.Double(x1, y1));
120:          r.add(new Point2D.Double(x1, y2));
121:          r.add(new Point2D.Double(x2, y2));
122:       }
123:       else if (bent == HVH)
124:       {
125:          double x1;
126:          double x2;
127:          double y1 = s.getCenterY();
128:          double y2 = e.getCenterY();
129:          if (s.getMaxX() + 2 * MIN_SEGMENT <= e.getX())
130:          {
131:             x1 = s.getMaxX();
132:             x2 = e.getX();
133:          }
134:          else if (e.getMaxX() + 2 * MIN_SEGMENT <= s.getX())
135:          {
136:             x1 = s.getX();
137:             x2 = e.getMaxX();
138:          }
139:          else return null;
140:          if (Math.abs(y1 - y2) <= MIN_SEGMENT)
141:          {
142:             r.add(new Point2D.Double(x1, (y1 + y2) / 2));
143:             r.add(new Point2D.Double(x2, (y1 + y2) / 2));
144:          }
145:          else
146:          {
147:             r.add(new Point2D.Double(x1, y1));
148:             r.add(new Point2D.Double((x1 + x2) / 2, y1));
149:             r.add(new Point2D.Double((x1 + x2) / 2, y2));
150:             r.add(new Point2D.Double(x2, y2));
151:          }
152:       }
153:       else if (bent == VHV)
154:       {
155:          double x1 = s.getCenterX();
156:          double x2 = e.getCenterX();
157:          double y1;
158:          double y2;
159:          if (s.getMaxY() + 2 * MIN_SEGMENT <= e.getY())
160:          {
161:             y1 = s.getMaxY();
162:             y2 = e.getY();
163:          }
164:          else if (e.getMaxY() + 2 * MIN_SEGMENT <= s.getY())
165:          {
166:             y1 = s.getY();
167:             y2 = e.getMaxY();
168: 
169:          }
170:          else return null;
171:          if (Math.abs(x1 - x2) <= MIN_SEGMENT)
172:          {
173:             r.add(new Point2D.Double((x1 + x2) / 2, y1));
174:             r.add(new Point2D.Double((x1 + x2) / 2, y2));
175:          }
176:          else
177:          {
178:             r.add(new Point2D.Double(x1, y1));
179:             r.add(new Point2D.Double(x1, (y1 + y2) / 2));
180:             r.add(new Point2D.Double(x2, (y1 + y2) / 2));
181:             r.add(new Point2D.Double(x2, y2));
182:          }
183:       }
184:       else return null;
185:       return r;
186:    }
187: 
188:    private static final int MIN_SEGMENT = 10;
189: }