View Javadoc

1   /*
2    * ObjectLab, http://www.objectlab.co.uk/open is supporting JTreeMap.
3    * 
4    * Based in London, we are world leaders in the design and development 
5    * of bespoke applications for the securities financing markets.
6    * 
7    * <a href="http://www.objectlab.co.uk/open">Click here to learn more</a>
8    *           ___  _     _           _   _          _
9    *          / _ \| |__ (_) ___  ___| |_| |    __ _| |__
10   *         | | | | '_ \| |/ _ \/ __| __| |   / _` | '_ \
11   *         | |_| | |_) | |  __/ (__| |_| |__| (_| | |_) |
12   *          \___/|_.__// |\___|\___|\__|_____\__,_|_.__/
13   *                   |__/
14   *
15   *                     www.ObjectLab.co.uk
16   *
17   * $Id: SplitSquarified.java 74 2006-10-24 22:19:05Z benoitx $
18   * 
19   * Copyright 2006 the original author or authors.
20   *
21   * Licensed under the Apache License, Version 2.0 (the "License"); you may not
22   * use this file except in compliance with the License. You may obtain a copy of
23   * the License at
24   *
25   * http://www.apache.org/licenses/LICENSE-2.0
26   *
27   * Unless required by applicable law or agreed to in writing, software
28   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
29   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
30   * License for the specific language governing permissions and limitations under
31   * the License.
32   */
33  package net.sf.jtreemap.swing;
34  
35  import java.util.Vector;
36  
37  /**
38   * The Squarified split strategy
39   * 
40   * @author Laurent DUTHEIL
41   */
42  public class SplitSquarified extends SplitStrategy {
43      /**
44       * 
45       */
46      private static final long serialVersionUID = 1711898915283018450L;
47  
48      private int w1;
49  
50      private int h1;
51  
52      private int x;
53  
54      private int y;
55  
56      private int w;
57  
58      private int h;
59  
60      private int x2;
61  
62      private int y2;
63  
64      private int w2;
65  
66      private int h2;
67  
68      @Override
69      public void splitElements(final Vector<TreeMapNode> v, final Vector<TreeMapNode> v1, final Vector<TreeMapNode> v2) {
70          int mid = 0;
71          final double weight0 = sumWeight(v);
72          final double a = v.get(mid).getWeight() / weight0;
73          double b = a;
74  
75          if (this.w < this.h) {
76              // height/width
77              while (mid < v.size()) {
78                  final double aspect = normAspect(this.h, this.w, a, b);
79                  final double q = v.get(mid).getWeight() / weight0;
80                  if (normAspect(this.h, this.w, a, b + q) > aspect) {
81                      break;
82                  }
83                  mid++;
84                  b += q;
85              }
86              int i = 0;
87              for (; i <= mid && i < v.size(); i++) {
88                  v1.add(v.get(i));
89              }
90              for (; i < v.size(); i++) {
91                  v2.add(v.get(i));
92              }
93              this.h1 = (int) Math.round(this.h * b);
94              this.w1 = this.w;
95              this.x2 = this.x;
96              this.y2 = (int) Math.round(this.y + this.h * b);
97              this.w2 = this.w;
98              this.h2 = this.h - this.h1;
99          } else {
100             // width/height
101             while (mid < v.size()) {
102                 final double aspect = normAspect(this.w, this.h, a, b);
103                 final double q = v.get(mid).getWeight() / weight0;
104                 if (normAspect(this.w, this.h, a, b + q) > aspect) {
105                     break;
106                 }
107                 mid++;
108                 b += q;
109             }
110             int i = 0;
111             for (; i <= mid && i < v.size(); i++) {
112                 v1.add(v.get(i));
113             }
114             for (; i < v.size(); i++) {
115                 v2.add(v.get(i));
116             }
117             this.h1 = this.h;
118             this.w1 = (int) Math.round(this.w * b);
119             this.x2 = (int) Math.round(this.x + this.w * b);
120             this.y2 = this.y;
121             this.w2 = this.w - this.w1;
122             this.h2 = this.h;
123         }
124     }
125 
126     /*
127      * (non-Javadoc)
128      * 
129      * @see net.sf.jtreemap.swing.SplitStrategy#calculatePositionsRec(int, int,
130      *      int, int, double, java.util.Vector)
131      */
132     @Override
133     protected void calculatePositionsRec(final int x0, final int y0, final int w0, final int h0, final double weight0,
134             final Vector<TreeMapNode> v) {
135         final Vector<TreeMapNode> vClone = new Vector<TreeMapNode>(v);
136 
137         sortVector(vClone);
138 
139         if (vClone.size() <= 2) {
140             SplitBySlice.splitInSlice(x0, y0, w0, h0, vClone, sumWeight(vClone));
141             calculateChildren(vClone);
142         } else {
143             final Vector<TreeMapNode> v1 = new Vector<TreeMapNode>();
144             final Vector<TreeMapNode> v2 = new Vector<TreeMapNode>();
145             this.x = x0;
146             this.y = y0;
147             this.w = w0;
148             this.h = h0;
149             splitElements(vClone, v1, v2);
150             // before the recurence, we have to "save" the values for the 2nd
151             // Vector
152             final int prevX2 = this.x2;
153             final int prevY2 = this.y2;
154             final int prevW2 = this.w2;
155             final int prevH2 = this.h2;
156             SplitBySlice.splitInSlice(x0, y0, this.w1, this.h1, v1, sumWeight(v1));
157             calculateChildren(v1);
158             calculatePositionsRec(prevX2, prevY2, prevW2, prevH2, sumWeight(v2), v2);
159         }
160 
161     }
162 
163     private double aspect(final double big, final double small, final double a, final double b) {
164         return (big * b) / (small * a / b);
165     }
166 
167     /**
168      * Execute the recurence for the children of the elements of the vector.<BR>
169      * Add also the borders if necessary
170      * 
171      * @param v
172      *            Vector with the elements to calculate
173      */
174     private void calculateChildren(final Vector<TreeMapNode> v) {
175         for (final TreeMapNode node : v) {
176             if (node.isLeaf()) {
177                 node.setX(node.getX() + TreeMapNode.getBorder());
178                 node.setY(node.getY() + TreeMapNode.getBorder());
179                 int width = node.getWidth() - TreeMapNode.getBorder();
180                 if (width < 0) {
181                     width = 0;
182                 }
183                 int height = node.getHeight() - TreeMapNode.getBorder();
184                 if (height < 0) {
185                     height = 0;
186                 }
187                 node.setHeight(height);
188                 node.setWidth(width);
189             } else {
190                 // if this is not a leaf, calculation for the children
191                 int bSub;
192                 if (TreeMapNode.getBorder() > 1) {
193                     bSub = 2;
194                 } else if (TreeMapNode.getBorder() == 1) {
195                     bSub = 1;
196                 } else {
197                     bSub = 0;
198                 }
199 
200                 int width = node.getWidth() - bSub;
201                 if (width < 0) {
202                     width = 0;
203                 }
204                 int height = node.getHeight() - bSub;
205                 if (height < 0) {
206                     height = 0;
207                 }
208 
209                 TreeMapNode.setBorder(TreeMapNode.getBorder() - bSub);
210                 calculatePositionsRec(node.getX() + bSub, node.getY() + bSub, width, height, node.getWeight(), node.getChildren());
211                 TreeMapNode.setBorder(TreeMapNode.getBorder() + bSub);
212             }
213 
214         }
215     }
216 
217     private double normAspect(final double big, final double small, final double a, final double b) {
218         final double xCalc = aspect(big, small, a, b);
219         if (xCalc < 1) {
220             return 1 / xCalc;
221         }
222         return xCalc;
223     }
224 }
225 /*
226  *                 ObjectLab is supporing JTreeMap
227  * 
228  * Based in London, we are world leaders in the design and development 
229  * of bespoke applications for the securities financing markets.
230  * 
231  * <a href="http://www.objectlab.co.uk/open">Click here to learn more about us</a>
232  *           ___  _     _           _   _          _
233  *          / _ \| |__ (_) ___  ___| |_| |    __ _| |__
234  *         | | | | '_ \| |/ _ \/ __| __| |   / _` | '_ \
235  *         | |_| | |_) | |  __/ (__| |_| |__| (_| | |_) |
236  *          \___/|_.__// |\___|\___|\__|_____\__,_|_.__/
237  *                   |__/
238  *
239  *                     www.ObjectLab.co.uk
240  */