View Javadoc

1   /*
2   
3       dsh-venn  Lightweight components for venn diagrams.
4       Copyright (c) 2009-2013 held jointly by the individual authors.
5   
6       This library is free software; you can redistribute it and/or modify it
7       under the terms of the GNU Lesser General Public License as published
8       by the Free Software Foundation; either version 3 of the License, or (at
9       your option) any later version.
10  
11      This library is distributed in the hope that it will be useful, but WITHOUT
12      ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
13      FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
14      License for more details.
15  
16      You should have received a copy of the GNU Lesser General Public License
17      along with this library;  if not, write to the Free Software Foundation,
18      Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA.
19  
20      > http://www.fsf.org/licensing/licenses/lgpl.html
21      > http://www.opensource.org/licenses/lgpl-license.php
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   * Immutable implementation of QuaternaryVennLayout.
43   *
44   * @author  Michael Heuer
45   */
46  public final class QuaternaryVennLayoutImpl
47      implements QuaternaryVennLayout
48  {
49      /** Shape for the first set. */
50      private final Shape firstShape;
51  
52      /** Shape for the second set. */
53      private final Shape secondShape;
54  
55      /** Shape for the third set. */
56      private final Shape thirdShape;
57  
58      /** Shape for the fourth set. */
59      private final Shape fourthShape;
60  
61      /** Lune center of the first only area. */
62      private final Point2D firstOnlyLuneCenter;
63  
64      /** Lune center of the second only area. */
65      private final Point2D secondOnlyLuneCenter;
66  
67      /** Lune center of the third only area. */
68      private final Point2D thirdOnlyLuneCenter;
69  
70      /** Lune center of the fourth only area. */
71      private final Point2D fourthOnlyLuneCenter;
72  
73      /** Lune center of the first second area. */
74      private final Point2D firstSecondLuneCenter;
75  
76      /** Lune center of the first third area. */
77      private final Point2D firstThirdLuneCenter;
78  
79      /** Lune center of the second third area. */
80      private final Point2D secondThirdLuneCenter;
81  
82      /** Lune center of the first fourth area. */
83      private final Point2D firstFourthLuneCenter;
84  
85      /** Lune center of the second fourth area. */
86      private final Point2D secondFourthLuneCenter;
87  
88      /** Lune center of the third fourth area. */
89      private final Point2D thirdFourthLuneCenter;
90  
91      /** Lune center of the first second third area. */
92      private final Point2D firstSecondThirdLuneCenter;
93  
94      /** Lune center of the first second fourth area. */
95      private final Point2D firstSecondFourthLuneCenter;
96  
97      /** Lune center of the first third fourth area. */
98      private final Point2D firstThirdFourthLuneCenter;
99  
100     /** Lune center of the second third fourth area. */
101     private final Point2D secondThirdFourthLuneCenter;
102 
103     /** Lune center of the intersection area. */
104     private final Point2D intersectionLuneCenter;
105 
106     /** Map of lune centers keyed by bit set. */
107     private final Map<ImmutableBitSet, Point2D> luneCenters;
108 
109     /** Bounding rectangle. */
110     private final Rectangle2D boundingRectangle;
111 
112 
113     /**
114      * Create a new quaternary venn layout with the specified parameters.
115      *
116      * @param firstShape shape for the first set, must not be null
117      * @param secondShape shape for the second set, must not be null
118      * @param thirdShape shape for the third set, must not be null
119      * @param fourthShape shape for the fourth set, must not be null
120      * @param firstOnlyLuneCenter lune center for the first only area
121      * @param secondOnlyLuneCenter lune center for the second only area
122      * @param thirdOnlyLuneCenter lune center for the third only area
123      * @param fourthOnlyLuneCenter lune center for the fourth only area
124      * @param firstSecondLuneCenter lune center for the first second area
125      * @param firstThirdLuneCenter lune center for the first third area
126      * @param secondThirdLuneCenter lune center for the second third area
127      * @param firstFourthLuneCenter lune center for the first fourth area
128      * @param secondFourthLuneCenter lune center for the second fourth area
129      * @param thirdFourthLuneCenter lune center for the third fourth area
130      * @param firstSecondThirdLuneCenter lune center for the first second third area
131      * @param firstSecondFourthLuneCenter lune center for the first second fourth area
132      * @param firstThirdFourthLuneCenter lune center for the first third fourth area
133      * @param secondThirdFourthLuneCenter lune center for the second third fourth area
134      * @param intersectionLuneCenter lune center for the intersection area
135      * @param boundingRectangle bounding rectangle, must not be null
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     /** {@inheritDoc} */
223     public Shape firstShape()
224     {
225         return firstShape;
226     }
227 
228     /** {@inheritDoc} */
229     public Shape secondShape()
230     {
231         return secondShape;
232     }
233 
234     /** {@inheritDoc} */
235     public Shape thirdShape()
236     {
237         return thirdShape;
238     }
239 
240     /** {@inheritDoc} */
241     public Shape fourthShape()
242     {
243         return fourthShape;
244     }
245 
246     /** {@inheritDoc} */
247     public Point2D firstOnlyLuneCenter()
248     {
249         return firstOnlyLuneCenter;
250     }
251 
252     /** {@inheritDoc} */
253     public Point2D secondOnlyLuneCenter()
254     {
255         return secondOnlyLuneCenter;
256     }
257 
258     /** {@inheritDoc} */
259     public Point2D thirdOnlyLuneCenter()
260     {
261         return thirdOnlyLuneCenter;
262     }
263 
264     /** {@inheritDoc} */
265     public Point2D fourthOnlyLuneCenter()
266     {
267         return fourthOnlyLuneCenter;
268     }
269 
270     /** {@inheritDoc} */
271     public Point2D firstSecondLuneCenter()
272     {
273         return firstSecondLuneCenter;
274     }
275 
276     /** {@inheritDoc} */
277     public Point2D firstThirdLuneCenter()
278     {
279         return firstThirdLuneCenter;
280     }
281 
282     /** {@inheritDoc} */
283     public Point2D secondThirdLuneCenter()
284     {
285         return secondThirdLuneCenter;
286     }
287 
288     /** {@inheritDoc} */
289     public Point2D firstFourthLuneCenter()
290     {
291         return firstFourthLuneCenter;
292     }
293 
294     /** {@inheritDoc} */
295     public Point2D secondFourthLuneCenter()
296     {
297         return secondFourthLuneCenter;
298     }
299 
300     /** {@inheritDoc} */
301     public Point2D thirdFourthLuneCenter()
302     {
303         return thirdFourthLuneCenter;
304     }
305 
306     /** {@inheritDoc} */
307     public Point2D firstSecondThirdLuneCenter()
308     {
309         return firstSecondThirdLuneCenter;
310     }
311 
312     /** {@inheritDoc} */
313     public Point2D firstSecondFourthLuneCenter()
314     {
315         return firstSecondFourthLuneCenter;
316     }
317 
318     /** {@inheritDoc} */
319     public Point2D firstThirdFourthLuneCenter()
320     {
321         return firstThirdFourthLuneCenter;
322     }
323 
324     /** {@inheritDoc} */
325     public Point2D secondThirdFourthLuneCenter()
326     {
327         return secondThirdFourthLuneCenter;
328     }
329 
330     /** {@inheritDoc} */
331     public Point2D intersectionLuneCenter()
332     {
333         return intersectionLuneCenter;
334     }
335 
336     /** {@inheritDoc} */
337     public int size()
338     {
339         return 4;
340     }
341 
342     /** {@inheritDoc} */
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     /** {@inheritDoc} */
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     /** {@inheritDoc} */
391     public Rectangle2D boundingRectangle()
392     {
393         return boundingRectangle;
394     }
395 }