1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 package org.dishevelled.venn.layouter;
25
26 import java.awt.geom.Area;
27 import java.awt.geom.Ellipse2D;
28 import java.awt.geom.Point2D;
29 import java.awt.geom.Rectangle2D;
30
31 import org.dishevelled.venn.VennModel;
32 import org.dishevelled.venn.BinaryVennLayout;
33 import org.dishevelled.venn.BinaryVennModel;
34 import org.dishevelled.venn.TernaryVennLayout;
35 import org.dishevelled.venn.TernaryVennModel;
36 import org.dishevelled.venn.QuaternaryVennLayout;
37 import org.dishevelled.venn.QuaternaryVennModel;
38 import org.dishevelled.venn.VennLayout;
39 import org.dishevelled.venn.VennLayouter;
40
41 import org.dishevelled.venn.layout.BinaryVennLayoutImpl;
42 import org.dishevelled.venn.layout.TernaryVennLayoutImpl;
43 import org.dishevelled.venn.layout.QuaternaryVennLayoutImpl;
44
45
46
47
48
49
50
51 public final class VennLayouterImpl<E> implements VennLayouter<E>
52 {
53
54
55 public VennLayout layout(final VennModel<E> model,
56 final Rectangle2D boundingRectangle,
57 final PerformanceHint performanceHint)
58 {
59 if (model == null)
60 {
61 throw new IllegalArgumentException("model must not be null");
62 }
63 if (boundingRectangle == null)
64 {
65 throw new IllegalArgumentException("boundingRectangle must not be null");
66 }
67 if (performanceHint == null)
68 {
69 throw new IllegalArgumentException("performanceHint must not be null");
70 }
71
72 if (model instanceof BinaryVennModel)
73 {
74 return layout((BinaryVennModel<E>) model, boundingRectangle);
75 }
76 else if (model instanceof TernaryVennModel)
77 {
78 return layout((TernaryVennModel<E>) model, boundingRectangle);
79 }
80 else if (model instanceof QuaternaryVennModel)
81 {
82 return layout((QuaternaryVennModel<E>) model, boundingRectangle);
83 }
84
85
86
87 return null;
88 }
89
90
91
92
93
94
95
96
97 BinaryVennLayout layout(final BinaryVennModel<E> model,
98 final Rectangle2D boundingRectangle)
99 {
100 double w = boundingRectangle.getWidth();
101 double h = boundingRectangle.getHeight();
102 double cx = w / 2.0d;
103 double cy = h / 2.0d;
104 double d = Math.min(h, 3.0d * w / 5.0d);
105 double r = d / 2.0d;
106 double x = cx - 5.0d * d / 6.0d;
107 double y = cy - d / 2.0d;
108
109 Ellipse2D firstShape = new Ellipse2D.Double(x, y, d, d);
110 Ellipse2D secondShape = new Ellipse2D.Double(x + 2.0d * d / 3.0d, y, d, d);
111 Point2D firstOnlyCenter = new Point2D.Double(cx - r, cy);
112 Point2D secondOnlyCenter = new Point2D.Double(cx + r, cy);
113 Point2D intersectionCenter = new Point2D.Double(cx, cy);
114
115 return new BinaryVennLayoutImpl(firstShape, secondShape,
116 firstOnlyCenter, secondOnlyCenter, intersectionCenter, boundingRectangle);
117 }
118
119
120
121
122
123
124
125
126 TernaryVennLayout layout(final TernaryVennModel<E> model,
127 final Rectangle2D boundingRectangle)
128 {
129 double w = boundingRectangle.getWidth();
130 double h = boundingRectangle.getHeight();
131 double d = 5.0d / (3.0d * Math.min(w, h));
132
133 Ellipse2D firstShape = new Ellipse2D.Double(0.0d, 0.0d, d, d);
134 Ellipse2D secondShape = new Ellipse2D.Double(((2.0d * d) / 3.0d), 0.0d, d, d);
135 Ellipse2D thirdShape = new Ellipse2D.Double(d / 3.0d, (2.0d * d) / 3.0d, d, d);
136
137 Area f = new Area(firstShape);
138 Area s = new Area(secondShape);
139 Area t = new Area(thirdShape);
140
141 Area firstOnly = new Area();
142 firstOnly.add(f);
143 firstOnly.subtract(s);
144 firstOnly.subtract(t);
145 Point2D firstOnlyCenter = centerOf(firstOnly);
146
147 Area secondOnly = new Area();
148 secondOnly.add(s);
149 secondOnly.subtract(f);
150 secondOnly.subtract(t);
151 Point2D secondOnlyCenter = centerOf(secondOnly);
152
153 Area thirdOnly = new Area();
154 thirdOnly.add(t);
155 thirdOnly.subtract(f);
156 thirdOnly.subtract(s);
157 Point2D thirdOnlyCenter = centerOf(thirdOnly);
158
159 Area firstSecond = new Area();
160 firstSecond.add(f);
161 firstSecond.intersect(s);
162 firstSecond.subtract(t);
163 Point2D firstSecondCenter = centerOf(firstSecond);
164
165 Area firstThird = new Area();
166 firstThird.add(f);
167 firstThird.intersect(t);
168 firstThird.subtract(s);
169 Point2D firstThirdCenter = centerOf(firstThird);
170
171 Area secondThird = new Area();
172 secondThird.add(s);
173 secondThird.intersect(t);
174 secondThird.subtract(f);
175 Point2D secondThirdCenter = centerOf(secondThird);
176
177 Area intersection = new Area();
178 intersection.add(f);
179 intersection.intersect(s);
180 intersection.intersect(t);
181 Point2D intersectionCenter = centerOf(intersection);
182
183 return new TernaryVennLayoutImpl(firstShape, secondShape, thirdShape, firstOnlyCenter, secondOnlyCenter,
184 thirdOnlyCenter, firstSecondCenter, firstThirdCenter, secondThirdCenter,
185 intersectionCenter, boundingRectangle);
186 }
187
188
189
190
191
192
193
194
195 QuaternaryVennLayout layout(final QuaternaryVennModel<E> model,
196 final Rectangle2D boundingRectangle)
197 {
198 return null;
199 }
200
201
202
203
204
205
206
207 static Point2D centerOf(final Area area)
208 {
209 if (area == null)
210 {
211 throw new IllegalArgumentException("area must not be null");
212 }
213 Rectangle2D rectangle = area.getBounds2D();
214 return new Point2D.Double(rectangle.getCenterX(), rectangle.getCenterY());
215 }
216 }