1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 package net.sf.jtreemap.swing;
34
35 import java.util.ArrayList;
36 import java.util.List;
37
38
39
40
41
42
43 public class SplitSquarified extends SplitStrategy {
44 private static final long serialVersionUID = 1711898915283018450L;
45 private int w1;
46 private int h1;
47 private int x;
48 private int y;
49 private int w;
50 private int h;
51 private int x2;
52 private int y2;
53 private int w2;
54 private int h2;
55
56 @Override
57 public void splitElements(final List<TreeMapNode> v, final List<TreeMapNode> v1, final List<TreeMapNode> v2) {
58 int mid = 0;
59 final double weight0 = sumWeight(v);
60 final double a = v.get(mid).getWeight() / weight0;
61 double b = a;
62
63 if (this.w < this.h) {
64
65 while (mid < v.size()) {
66 final double aspect = normAspect(this.h, this.w, a, b);
67 final double q = v.get(mid).getWeight() / weight0;
68 if (normAspect(this.h, this.w, a, b + q) > aspect) {
69 break;
70 }
71 mid++;
72 b += q;
73 }
74 int i = 0;
75 for (; i <= mid && i < v.size(); i++) {
76 v1.add(v.get(i));
77 }
78 for (; i < v.size(); i++) {
79 v2.add(v.get(i));
80 }
81 this.h1 = (int) Math.round(this.h * b);
82 this.w1 = this.w;
83 this.x2 = this.x;
84 this.y2 = (int) Math.round(this.y + this.h * b);
85 this.w2 = this.w;
86 this.h2 = this.h - this.h1;
87 } else {
88 widthSameOrBiggerThanHeight(v, v1, v2, mid, weight0, a, b);
89 }
90 }
91
92 private void widthSameOrBiggerThanHeight(final List<TreeMapNode> v, final List<TreeMapNode> v1, final List<TreeMapNode> v2, int mid,
93 final double weight0, final double a, double b) {
94
95 while (mid < v.size()) {
96 final double aspect = normAspect(this.w, this.h, a, b);
97 final double q = v.get(mid).getWeight() / weight0;
98 if (normAspect(this.w, this.h, a, b + q) > aspect) {
99 break;
100 }
101 mid++;
102 b += q;
103 }
104 int i = 0;
105 for (; i <= mid && i < v.size(); i++) {
106 v1.add(v.get(i));
107 }
108 for (; i < v.size(); i++) {
109 v2.add(v.get(i));
110 }
111 this.h1 = this.h;
112 this.w1 = (int) Math.round(this.w * b);
113 this.x2 = (int) Math.round(this.x + this.w * b);
114 this.y2 = this.y;
115 this.w2 = this.w - this.w1;
116 this.h2 = this.h;
117 }
118
119
120
121
122
123
124
125 @Override
126 protected void calculatePositionsRec(final int x0, final int y0, final int w0, final int h0, final double weight0, final List<TreeMapNode> v) {
127
128 if (w0 * h0 < 20) {
129 return;
130 }
131
132
133 if (w0 * h0 < v.size()) {
134 return;
135 }
136
137 final List<TreeMapNode> vClone = new ArrayList<>(v);
138
139 sortList(vClone);
140
141 if (vClone.size() <= 2) {
142 SplitBySlice.splitInSlice(x0, y0, w0, h0, vClone, sumWeight(vClone));
143 calculateChildren(vClone);
144 } else {
145 final List<TreeMapNode> v1 = new ArrayList<>();
146 final List<TreeMapNode> v2 = new ArrayList<>();
147 this.x = x0;
148 this.y = y0;
149 this.w = w0;
150 this.h = h0;
151 splitElements(vClone, v1, v2);
152
153
154 final int prevX2 = this.x2;
155 final int prevY2 = this.y2;
156 final int prevW2 = this.w2;
157 final int prevH2 = this.h2;
158 SplitBySlice.splitInSlice(x0, y0, this.w1, this.h1, v1, sumWeight(v1));
159 calculateChildren(v1);
160 calculatePositionsRec(prevX2, prevY2, prevW2, prevH2, sumWeight(v2), v2);
161 }
162
163 }
164
165 private double aspect(final double big, final double small, final double a, final double b) {
166 return big * b / (small * a / b);
167 }
168
169
170
171
172
173
174
175
176 private void calculateChildren(final List<TreeMapNode> v) {
177 for (final TreeMapNode node : v) {
178 if (node.isLeaf()) {
179 node.setX(node.getX() + TreeMapNode.getBorder());
180 node.setY(node.getY() + TreeMapNode.getBorder());
181 int width = node.getWidth() - TreeMapNode.getBorder();
182 if (width < 0) {
183 width = 0;
184 }
185 int height = node.getHeight() - TreeMapNode.getBorder();
186 if (height < 0) {
187 height = 0;
188 }
189 node.setHeight(height);
190 node.setWidth(width);
191 } else {
192 calculateNonLeaf(node);
193 }
194 }
195 }
196
197 private void calculateNonLeaf(final TreeMapNode node) {
198
199 int bSub;
200 if (TreeMapNode.getBorder() > 1) {
201 bSub = 2;
202 } else if (TreeMapNode.getBorder() == 1) {
203 bSub = 1;
204 } else {
205 bSub = 0;
206 }
207
208 int width = node.getWidth() - bSub;
209 if (width < 0) {
210 width = 0;
211 }
212 int height = node.getHeight() - bSub;
213 if (height < 0) {
214 height = 0;
215 }
216
217 TreeMapNode.setBorder(TreeMapNode.getBorder() - bSub);
218 calculatePositionsRec(node.getX() + bSub, node.getY() + bSub, width, height, node.getWeight(), node.getChildren());
219 TreeMapNode.setBorder(TreeMapNode.getBorder() + bSub);
220 }
221
222 private double normAspect(final double big, final double small, final double a, final double b) {
223 final double xCalc = aspect(big, small, a, b);
224 if (xCalc < 1) {
225 return 1 / xCalc;
226 }
227 return xCalc;
228 }
229 }
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245