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 75 2006-10-24 23:00:51Z 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.ktreemap;
34  
35  import java.util.ArrayList;
36  import java.util.List;
37  
38  import org.eclipse.swt.graphics.Rectangle;
39  
40  /**
41   * The Squarified split strategy
42   *
43   * @author Laurent DUTHEIL
44   */
45  public class SplitSquarified extends SplitStrategy {
46    private int w1, h1;
47    private int x, y, w, h;
48    private int x2, y2, w2, h2;
49  
50    @Override
51    public void splitElements(List<TreeMapNode> list, List<TreeMapNode> group1,
52        List<TreeMapNode> group2) {
53      int mid = 0;
54      double weight0 = sumWeight(list);
55      double a = list.get(mid).getWeight() / weight0;
56      double b = a;
57  
58      if (this.w < this.h) {
59        // height/width
60        while (mid < list.size()) {
61          double aspect = normAspect(this.h, this.w, a, b);
62          double q = list.get(mid).getWeight() / weight0;
63          if (normAspect(this.h, this.w, a, b + q) > aspect) {
64            break;
65          }
66          mid++;
67          b += q;
68        }
69        int i = 0;
70        for (; i <= mid && i < list.size(); i++) {
71          group1.add(list.get(i));
72        }
73        for (; i < list.size(); i++) {
74          group2.add(list.get(i));
75        }
76        this.h1 = (int)Math.round(this.h * b);
77        this.w1 = this.w;
78        this.x2 = this.x;
79        this.y2 = (int)Math.round(this.y + this.h * b);
80        this.w2 = this.w;
81        this.h2 = this.h - this.h1;
82      } else {
83        // width/height
84        while (mid < list.size()) {
85          double aspect = normAspect(this.w, this.h, a, b);
86          double q = list.get(mid).getWeight() / weight0;
87          if (normAspect(this.w, this.h, a, b + q) > aspect) {
88            break;
89          }
90          mid++;
91          b += q;
92        }
93        int i = 0;
94        for (; i <= mid && i < list.size(); i++) {
95          group1.add(list.get(i));
96        }
97        for (; i < list.size(); i++) {
98          group2.add(list.get(i));
99        }
100       this.h1 = this.h;
101       this.w1 = (int)Math.round(this.w * b);
102       this.x2 = (int)Math.round(this.x + this.w * b);
103       this.y2 = this.y;
104       this.w2 = this.w - this.w1;
105       this.h2 = this.h;
106     }
107   }
108 
109   /*
110    * (non-Javadoc)
111    *
112    * @see net.sf.jtreemap.swing.SplitStrategy#calculatePositionsRec(int, int,
113    *      int, int, double, java.util.Vector)
114    */
115   @Override
116   protected void calculatePositionsRec(Rectangle bounds, double weight0,
117       List<TreeMapNode> children) {
118     List<TreeMapNode> listClone = new ArrayList<TreeMapNode>(children);
119 
120     sortList(listClone);
121 
122     if (listClone.size() <= 2) {
123       SplitBySlice.splitInSlice(bounds, listClone, sumWeight(listClone));
124       calculateChildren(listClone);
125     } else {
126       List<TreeMapNode> l1 = new ArrayList<TreeMapNode>();
127       List<TreeMapNode> l2 = new ArrayList<TreeMapNode>();
128       this.x = bounds.x;
129       this.y = bounds.y;
130       this.w = bounds.width;
131       this.h = bounds.height;
132       splitElements(listClone, l1, l2);
133       // before the recurence, we have to "save" the values for the 2nd Vector
134       int x2 = this.x2;
135       int y2 = this.y2;
136       int w2 = this.w2;
137       int h2 = this.h2;
138       Rectangle bounds1 = new Rectangle(bounds.x, bounds.y, this.w1, this.h1);
139       SplitBySlice.splitInSlice(bounds1, l1, sumWeight(l1));
140       calculateChildren(l1);
141       Rectangle bounds2 = new Rectangle(x2, y2, w2, h2);
142       calculatePositionsRec(bounds2, sumWeight(l2), l2);
143     }
144 
145   }
146 
147   private double aspect(double big, double small, double a, double b) {
148     return (big * b) / (small * a / b);
149   }
150 
151   /**
152    * Execute the recurence for the children of the elements of the vector.<BR>
153    * Add also the borders if necessary
154    *
155    * @param v Vector with the elements to calculate
156    */
157   private void calculateChildren(List<TreeMapNode> v) {
158     for (TreeMapNode node : v) {
159       if (node.isLeaf()) {
160         node.setX(node.getX() + TreeMapNode.getBorder());
161         node.setY(node.getY() + TreeMapNode.getBorder());
162         int w = node.getWidth() - TreeMapNode.getBorder();
163         if (w < 0) {
164           w = 0;
165         }
166         int h = node.getHeight() - TreeMapNode.getBorder();
167         if (h < 0) {
168           h = 0;
169         }
170         node.setHeight(h);
171         node.setWidth(w);
172       } else {
173         // if this is not a leaf, calculation for the children
174         int bSub;
175         if (TreeMapNode.getBorder() > 1) {
176           bSub = 2;
177         } else if (TreeMapNode.getBorder() == 1) {
178           bSub = 1;
179         } else {
180           bSub = 0;
181         }
182 
183         int w = node.getWidth() - bSub;
184         if (w < 0) {
185           w = 0;
186         }
187         int h = node.getHeight() - bSub;
188         if (h < 0) {
189           h = 0;
190         }
191 
192         TreeMapNode.setBorder(TreeMapNode.getBorder() - bSub);
193         Rectangle newBounds = new Rectangle(node.getX() + bSub, node.getY()
194             + bSub, w, h);
195         calculatePositionsRec(newBounds, node.getWeight(), node.getChildren());
196         TreeMapNode.setBorder(TreeMapNode.getBorder() + bSub);
197       }
198 
199     }
200   }
201 
202   private double normAspect(double big, double small, double a, double b) {
203     double x = aspect(big, small, a, b);
204     if (x < 1) {
205       return 1 / x;
206     }
207     return x;
208   }
209 
210 }
211 /*
212  *                 ObjectLab is supporing JTreeMap
213  * 
214  * Based in London, we are world leaders in the design and development 
215  * of bespoke applications for the securities financing markets.
216  * 
217  * <a href="http://www.objectlab.co.uk/open">Click here to learn more about us</a>
218  *           ___  _     _           _   _          _
219  *          / _ \| |__ (_) ___  ___| |_| |    __ _| |__
220  *         | | | | '_ \| |/ _ \/ __| __| |   / _` | '_ \
221  *         | |_| | |_) | |  __/ (__| |_| |__| (_| | |_) |
222  *          \___/|_.__// |\___|\___|\__|_____\__,_|_.__/
223  *                   |__/
224  *
225  *                     www.ObjectLab.co.uk
226  */