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