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.BinaryVennLayout;
38  
39  import static org.dishevelled.venn.layout.VennLayoutUtils.toImmutableBitSet;
40  
41  /**
42   * Immutable implementation of BinaryVennLayout.
43   *
44   * @author  Michael Heuer
45   */
46  public final class BinaryVennLayoutImpl
47      implements BinaryVennLayout
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      /** Lune center of the first only area. */
56      private final Point2D firstOnlyLuneCenter;
57  
58      /** Lune center of the second only area. */
59      private final Point2D secondOnlyLuneCenter;
60  
61      /** Lune center of the intersection area. */
62      private final Point2D intersectionLuneCenter;
63  
64      /** Map of lune centers keyed by bit set. */
65      private final Map<ImmutableBitSet, Point2D> luneCenters;
66  
67      /** Bounding rectangle. */
68      private final Rectangle2D boundingRectangle;
69  
70  
71      /**
72       * Create a new binary venn layout with the specified parameters.
73       *
74       * @param firstShape shape for the first set, must not be null
75       * @param secondShape shape for the second set, must not be null
76       * @param firstOnlyLuneCenter lune center for the first only area
77       * @param secondOnlyLuneCenter lune center for the second only area
78       * @param intersectionLuneCenter lune center for the intersection area
79       * @param boundingRectangle bounding rectangle, must not be null
80       */
81      public BinaryVennLayoutImpl(final Shape firstShape,
82                                  final Shape secondShape,
83                                  final Point2D firstOnlyLuneCenter,
84                                  final Point2D secondOnlyLuneCenter,
85                                  final Point2D intersectionLuneCenter,
86                                  final Rectangle2D boundingRectangle)
87      {
88          if (firstShape == null)
89          {
90              throw new IllegalArgumentException("firstShape must not be null");
91          }
92          if (secondShape == null)
93          {
94              throw new IllegalArgumentException("secondShape must not be null");
95          }
96          if (boundingRectangle == null)
97          {
98              throw new IllegalArgumentException("boundingRectangle must not be null");
99          }
100         // todo: defensive copy?
101         this.firstShape = firstShape;
102         this.secondShape = secondShape;
103         this.firstOnlyLuneCenter = firstOnlyLuneCenter;
104         this.secondOnlyLuneCenter = secondOnlyLuneCenter;
105         this.intersectionLuneCenter = intersectionLuneCenter;
106         this.boundingRectangle = boundingRectangle;
107 
108         luneCenters = Maps.newHashMapWithExpectedSize(3);
109 
110         luneCenters.put(toImmutableBitSet(0), this.firstOnlyLuneCenter);
111         luneCenters.put(toImmutableBitSet(1), this.secondOnlyLuneCenter);
112 
113         luneCenters.put(toImmutableBitSet(0, 1), this.intersectionLuneCenter);
114         // copy to immutable map?
115     }
116 
117 
118     /** {@inheritDoc} */
119     public Shape firstShape()
120     {
121         // todo:  defensive copy?
122         return firstShape;
123     }
124 
125     /** {@inheritDoc} */
126     public Shape secondShape()
127     {
128         return secondShape;
129     }
130 
131     /** {@inheritDoc} */
132     public Point2D firstOnlyLuneCenter()
133     {
134         return firstOnlyLuneCenter;
135     }
136 
137     /** {@inheritDoc} */
138     public Point2D secondOnlyLuneCenter()
139     {
140         return secondOnlyLuneCenter;
141     }
142 
143     /** {@inheritDoc} */
144     public Point2D intersectionLuneCenter()
145     {
146         return intersectionLuneCenter;
147     }
148 
149     /** {@inheritDoc} */
150     public int size()
151     {
152         return 2;
153     }
154 
155     /** {@inheritDoc} */
156     public Shape get(final int index)
157     {
158         if (index < 0 || index > 1)
159         {
160             throw new IndexOutOfBoundsException("index out of bounds");
161         }
162         switch (index)
163         {
164         case 0:
165             return firstShape;
166         case 1:
167             return secondShape;
168         default:
169             break;
170         }
171         throw new IllegalStateException("invalid index " + index);
172     }
173 
174     /** {@inheritDoc} */
175     public Point2D luneCenter(final int index, final int... additional)
176     {
177         int maxIndex = size() - 1;
178         if (index < 0 || index > maxIndex)
179         {
180             throw new IndexOutOfBoundsException("index out of bounds");
181         }
182         if (additional != null && additional.length > 0)
183         {
184             if (additional.length > maxIndex)
185             {
186                 throw new IndexOutOfBoundsException("too many indices provided");
187             }
188             for (int i = 0, size = additional.length; i < size; i++)
189             {
190                 if (additional[i] < 0 || additional[i] > maxIndex)
191                 {
192                     throw new IndexOutOfBoundsException("additional index [" + i + "] out of bounds");
193                 }
194             }
195         }
196         return luneCenters.get(toImmutableBitSet(index, additional));
197     }
198 
199     /** {@inheritDoc} */
200     public Rectangle2D boundingRectangle()
201     {
202         return boundingRectangle;
203     }
204 }