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.layout;
25
26 import java.awt.Shape;
27
28 import java.awt.geom.Point2D;
29 import java.awt.geom.Rectangle2D;
30
31 import java.util.Map;
32
33 import com.google.common.collect.Maps;
34
35 import org.dishevelled.bitset.ImmutableBitSet;
36
37 import org.dishevelled.venn.QuaternaryVennLayout;
38
39 import static org.dishevelled.venn.layout.VennLayoutUtils.toImmutableBitSet;
40
41
42
43
44
45
46 public final class QuaternaryVennLayoutImpl
47 implements QuaternaryVennLayout
48 {
49
50 private final Shape firstShape;
51
52
53 private final Shape secondShape;
54
55
56 private final Shape thirdShape;
57
58
59 private final Shape fourthShape;
60
61
62 private final Point2D firstOnlyLuneCenter;
63
64
65 private final Point2D secondOnlyLuneCenter;
66
67
68 private final Point2D thirdOnlyLuneCenter;
69
70
71 private final Point2D fourthOnlyLuneCenter;
72
73
74 private final Point2D firstSecondLuneCenter;
75
76
77 private final Point2D firstThirdLuneCenter;
78
79
80 private final Point2D secondThirdLuneCenter;
81
82
83 private final Point2D firstFourthLuneCenter;
84
85
86 private final Point2D secondFourthLuneCenter;
87
88
89 private final Point2D thirdFourthLuneCenter;
90
91
92 private final Point2D firstSecondThirdLuneCenter;
93
94
95 private final Point2D firstSecondFourthLuneCenter;
96
97
98 private final Point2D firstThirdFourthLuneCenter;
99
100
101 private final Point2D secondThirdFourthLuneCenter;
102
103
104 private final Point2D intersectionLuneCenter;
105
106
107 private final Map<ImmutableBitSet, Point2D> luneCenters;
108
109
110 private final Rectangle2D boundingRectangle;
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137 public QuaternaryVennLayoutImpl(final Shape firstShape,
138 final Shape secondShape,
139 final Shape thirdShape,
140 final Shape fourthShape,
141 final Point2D firstOnlyLuneCenter,
142 final Point2D secondOnlyLuneCenter,
143 final Point2D thirdOnlyLuneCenter,
144 final Point2D fourthOnlyLuneCenter,
145 final Point2D firstSecondLuneCenter,
146 final Point2D firstThirdLuneCenter,
147 final Point2D secondThirdLuneCenter,
148 final Point2D firstFourthLuneCenter,
149 final Point2D secondFourthLuneCenter,
150 final Point2D thirdFourthLuneCenter,
151 final Point2D firstSecondThirdLuneCenter,
152 final Point2D firstSecondFourthLuneCenter,
153 final Point2D firstThirdFourthLuneCenter,
154 final Point2D secondThirdFourthLuneCenter,
155 final Point2D intersectionLuneCenter,
156 final Rectangle2D boundingRectangle)
157 {
158 if (firstShape == null)
159 {
160 throw new IllegalArgumentException("firstShape must not be null");
161 }
162 if (secondShape == null)
163 {
164 throw new IllegalArgumentException("secondShape must not be null");
165 }
166 if (thirdShape == null)
167 {
168 throw new IllegalArgumentException("thirdShape must not be null");
169 }
170 if (fourthShape == null)
171 {
172 throw new IllegalArgumentException("fourthShape must not be null");
173 }
174 if (boundingRectangle == null)
175 {
176 throw new IllegalArgumentException("boundingRectangle must not be null");
177 }
178 this.firstShape = firstShape;
179 this.secondShape = secondShape;
180 this.thirdShape = thirdShape;
181 this.fourthShape = fourthShape;
182 this.firstOnlyLuneCenter = firstOnlyLuneCenter;
183 this.secondOnlyLuneCenter = secondOnlyLuneCenter;
184 this.thirdOnlyLuneCenter = thirdOnlyLuneCenter;
185 this.fourthOnlyLuneCenter = fourthOnlyLuneCenter;
186 this.firstSecondLuneCenter = firstSecondLuneCenter;
187 this.firstThirdLuneCenter = firstThirdLuneCenter;
188 this.secondThirdLuneCenter = secondThirdLuneCenter;
189 this.firstFourthLuneCenter = firstFourthLuneCenter;
190 this.secondFourthLuneCenter = secondFourthLuneCenter;
191 this.thirdFourthLuneCenter = thirdFourthLuneCenter;
192 this.firstSecondThirdLuneCenter = firstSecondThirdLuneCenter;
193 this.firstSecondFourthLuneCenter = firstSecondFourthLuneCenter;
194 this.firstThirdFourthLuneCenter = firstThirdFourthLuneCenter;
195 this.secondThirdFourthLuneCenter = secondThirdFourthLuneCenter;
196 this.intersectionLuneCenter = intersectionLuneCenter;
197 this.boundingRectangle = boundingRectangle;
198
199 luneCenters = Maps.newHashMapWithExpectedSize(15);
200
201 luneCenters.put(toImmutableBitSet(0), this.firstOnlyLuneCenter);
202 luneCenters.put(toImmutableBitSet(1), this.secondOnlyLuneCenter);
203 luneCenters.put(toImmutableBitSet(2), this.thirdOnlyLuneCenter);
204 luneCenters.put(toImmutableBitSet(3), this.fourthOnlyLuneCenter);
205
206 luneCenters.put(toImmutableBitSet(0, 1), this.firstSecondLuneCenter);
207 luneCenters.put(toImmutableBitSet(0, 2), this.firstThirdLuneCenter);
208 luneCenters.put(toImmutableBitSet(0, 3), this.firstFourthLuneCenter);
209 luneCenters.put(toImmutableBitSet(1, 2), this.secondThirdLuneCenter);
210 luneCenters.put(toImmutableBitSet(1, 3), this.secondFourthLuneCenter);
211 luneCenters.put(toImmutableBitSet(2, 3), this.thirdFourthLuneCenter);
212
213 luneCenters.put(toImmutableBitSet(0, 1, 2), this.firstSecondThirdLuneCenter);
214 luneCenters.put(toImmutableBitSet(0, 1, 3), this.firstSecondFourthLuneCenter);
215 luneCenters.put(toImmutableBitSet(0, 2, 3), this.firstThirdFourthLuneCenter);
216 luneCenters.put(toImmutableBitSet(1, 2, 3), this.secondThirdFourthLuneCenter);
217
218 luneCenters.put(toImmutableBitSet(0, 1, 2, 3), this.intersectionLuneCenter);
219 }
220
221
222
223 public Shape firstShape()
224 {
225 return firstShape;
226 }
227
228
229 public Shape secondShape()
230 {
231 return secondShape;
232 }
233
234
235 public Shape thirdShape()
236 {
237 return thirdShape;
238 }
239
240
241 public Shape fourthShape()
242 {
243 return fourthShape;
244 }
245
246
247 public Point2D firstOnlyLuneCenter()
248 {
249 return firstOnlyLuneCenter;
250 }
251
252
253 public Point2D secondOnlyLuneCenter()
254 {
255 return secondOnlyLuneCenter;
256 }
257
258
259 public Point2D thirdOnlyLuneCenter()
260 {
261 return thirdOnlyLuneCenter;
262 }
263
264
265 public Point2D fourthOnlyLuneCenter()
266 {
267 return fourthOnlyLuneCenter;
268 }
269
270
271 public Point2D firstSecondLuneCenter()
272 {
273 return firstSecondLuneCenter;
274 }
275
276
277 public Point2D firstThirdLuneCenter()
278 {
279 return firstThirdLuneCenter;
280 }
281
282
283 public Point2D secondThirdLuneCenter()
284 {
285 return secondThirdLuneCenter;
286 }
287
288
289 public Point2D firstFourthLuneCenter()
290 {
291 return firstFourthLuneCenter;
292 }
293
294
295 public Point2D secondFourthLuneCenter()
296 {
297 return secondFourthLuneCenter;
298 }
299
300
301 public Point2D thirdFourthLuneCenter()
302 {
303 return thirdFourthLuneCenter;
304 }
305
306
307 public Point2D firstSecondThirdLuneCenter()
308 {
309 return firstSecondThirdLuneCenter;
310 }
311
312
313 public Point2D firstSecondFourthLuneCenter()
314 {
315 return firstSecondFourthLuneCenter;
316 }
317
318
319 public Point2D firstThirdFourthLuneCenter()
320 {
321 return firstThirdFourthLuneCenter;
322 }
323
324
325 public Point2D secondThirdFourthLuneCenter()
326 {
327 return secondThirdFourthLuneCenter;
328 }
329
330
331 public Point2D intersectionLuneCenter()
332 {
333 return intersectionLuneCenter;
334 }
335
336
337 public int size()
338 {
339 return 4;
340 }
341
342
343 public Shape get(final int index)
344 {
345 if (index < 0 || index > 3)
346 {
347 throw new IndexOutOfBoundsException("index out of bounds");
348 }
349 switch (index)
350 {
351 case 0:
352 return firstShape;
353 case 1:
354 return secondShape;
355 case 2:
356 return thirdShape;
357 case 3:
358 return fourthShape;
359 default:
360 break;
361 }
362 throw new IllegalStateException("invalid index " + index);
363 }
364
365
366 public Point2D luneCenter(final int index, final int... additional)
367 {
368 int maxIndex = size() - 1;
369 if (index < 0 || index > maxIndex)
370 {
371 throw new IndexOutOfBoundsException("index out of bounds");
372 }
373 if (additional != null && additional.length > 0)
374 {
375 if (additional.length > maxIndex)
376 {
377 throw new IndexOutOfBoundsException("too many indices provided");
378 }
379 for (int i = 0, size = additional.length; i < size; i++)
380 {
381 if (additional[i] < 0 || additional[i] > maxIndex)
382 {
383 throw new IndexOutOfBoundsException("additional index [" + i + "] out of bounds");
384 }
385 }
386 }
387 return luneCenters.get(toImmutableBitSet(index, additional));
388 }
389
390
391 public Rectangle2D boundingRectangle()
392 {
393 return boundingRectangle;
394 }
395 }