1 | /* |
---|
2 | * This program is free software; you can redistribute it and/or modify |
---|
3 | * it under the terms of the GNU General Public License as published by |
---|
4 | * the Free Software Foundation; either version 2 of the License, or |
---|
5 | * (at your option) any later version. |
---|
6 | * |
---|
7 | * This program is distributed in the hope that it will be useful, |
---|
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
10 | * GNU General Public License for more details. |
---|
11 | * |
---|
12 | * You should have received a copy of the GNU General Public License |
---|
13 | * along with this program; if not, write to the Free Software |
---|
14 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
---|
15 | */ |
---|
16 | |
---|
17 | /* |
---|
18 | * PlaceNode2.java |
---|
19 | * Copyright (C) 1999 University of Waikato, Hamilton, New Zealand |
---|
20 | * |
---|
21 | */ |
---|
22 | |
---|
23 | package weka.gui.treevisualizer; |
---|
24 | |
---|
25 | import java.util.*; |
---|
26 | |
---|
27 | /** |
---|
28 | * This class will place the Nodes of a tree. <p> |
---|
29 | * |
---|
30 | * It will place these nodes so that they fall at evenly below their parent. |
---|
31 | * It will then go through and look for places where nodes fall on the wrong |
---|
32 | * side of other nodes |
---|
33 | * when it finds one it will trace back up the tree to find the first common |
---|
34 | * sibling group these two nodes have |
---|
35 | * And it will adjust the spacing between these two siblings so that the two |
---|
36 | * nodes no longer overlap. |
---|
37 | * This is nasty to calculate with , and takes a while with the current |
---|
38 | * algorithm I am using to do this.<p> |
---|
39 | * |
---|
40 | * |
---|
41 | * @author Malcolm Ware (mfw4@cs.waikato.ac.nz) |
---|
42 | * @version $Revision: 1.4 $ |
---|
43 | */ |
---|
44 | public class PlaceNode2 implements NodePlace { |
---|
45 | /** The space each row will take up. */ |
---|
46 | private double m_yRatio; |
---|
47 | |
---|
48 | /** An array that lists the groups and information about them. */ |
---|
49 | private Group[] m_groups; |
---|
50 | |
---|
51 | /** An array that lists the levels and information about them. */ |
---|
52 | private Level[] m_levels; |
---|
53 | |
---|
54 | /** The Number of groups the tree has */ |
---|
55 | private int m_groupNum; |
---|
56 | |
---|
57 | /** The number of levels the group tree has */ |
---|
58 | private int m_levelNum; |
---|
59 | |
---|
60 | /** |
---|
61 | * The Funtion to call to have the nodes arranged. |
---|
62 | * |
---|
63 | * @param r The top node of the tree to arrange. |
---|
64 | */ |
---|
65 | public void place(Node r) { |
---|
66 | //note i might write count groups into the node class as well as |
---|
67 | //it may be useful too; |
---|
68 | |
---|
69 | m_groupNum = Node.getGCount(r,0); //i could swap over to the node class |
---|
70 | //group count,but this works os i'm not gonna |
---|
71 | m_groups = new Group[m_groupNum]; |
---|
72 | |
---|
73 | for (int noa = 0;noa < m_groupNum;noa++) { |
---|
74 | m_groups[noa] = new Group(); |
---|
75 | m_groups[noa].m_gap = 3; |
---|
76 | m_groups[noa].m_start = -1; |
---|
77 | } |
---|
78 | |
---|
79 | groupBuild(r); |
---|
80 | m_levelNum = Node.getHeight(r,0); |
---|
81 | m_yRatio = 1 / (double)(m_levelNum + 1); |
---|
82 | |
---|
83 | m_levels = new Level[m_levelNum]; |
---|
84 | |
---|
85 | for (int noa = 0;noa < m_levelNum;noa++) { |
---|
86 | m_levels[noa] = new Level(); |
---|
87 | } |
---|
88 | r.setTop(m_yRatio); |
---|
89 | yPlacer(); |
---|
90 | r.setCenter(0); |
---|
91 | xPlacer(0); |
---|
92 | |
---|
93 | |
---|
94 | //ok now i just have to untangle then scale down |
---|
95 | //note instead of starting with coords between 1 and 0 i will |
---|
96 | //use ints then scale them down |
---|
97 | //i will scale them down either by all relative to the largest |
---|
98 | //line or by each line individually |
---|
99 | |
---|
100 | untangle2(); |
---|
101 | |
---|
102 | scaleByMax(); |
---|
103 | //scaleByInd(); |
---|
104 | } |
---|
105 | |
---|
106 | |
---|
107 | /* |
---|
108 | private void thinner() |
---|
109 | { |
---|
110 | //what this function does is it retains the symmetry of the |
---|
111 | // parent node about the children but the children are no longer evenly |
---|
112 | //spaced this stops children from being pushed too far to the sides |
---|
113 | //,note this algorithm may need the method altered as it may |
---|
114 | // require heavy optimisation to go at any decent speed |
---|
115 | |
---|
116 | Node r,s; |
---|
117 | Edge e; |
---|
118 | double parent_x; |
---|
119 | for (int noa = group_num - 1;noa >= 0;noa--) |
---|
120 | { |
---|
121 | Vector shifts = new Vector(20,10); |
---|
122 | shifts.addElement(0); |
---|
123 | int g_num = 0;//this is the offset from groups.m_start to get the right 1 |
---|
124 | r = groups[noa].m_p; |
---|
125 | parent_x = r.getCenter(); |
---|
126 | for (int nob = 1;(e = r.getChild(nob)) != null;nob++) |
---|
127 | { |
---|
128 | double margin; |
---|
129 | s = e.getTarget(); |
---|
130 | margin = s_getCenter - r.getChild(nob - 1).getTarget().getCenter-1 |
---|
131 | - shift.elementAt(nob-1); |
---|
132 | if (margin > 0) |
---|
133 | { |
---|
134 | margin = check_down(s,g_num,margin); |
---|
135 | if (margin > 0) |
---|
136 | { |
---|
137 | shift.addElement(-margin); |
---|
138 | } |
---|
139 | else |
---|
140 | { |
---|
141 | shift.addElement(0); |
---|
142 | } |
---|
143 | } |
---|
144 | else |
---|
145 | { |
---|
146 | shift.addElement(0); |
---|
147 | } |
---|
148 | if (s.getChild(0) != null) |
---|
149 | { |
---|
150 | g_num++; |
---|
151 | } |
---|
152 | } |
---|
153 | } |
---|
154 | } |
---|
155 | |
---|
156 | |
---|
157 | private double check_down(Node r,int gn,double m) |
---|
158 | { |
---|
159 | //note i need to know where the children of the |
---|
160 | //other changers are to properly overlap check |
---|
161 | //to do this i think the best way is to go up the other group |
---|
162 | //parents line and see if it goes through the current group |
---|
163 | //this means to save time i need to know the level that is being |
---|
164 | //worked with along with the group |
---|
165 | |
---|
166 | Edge e; |
---|
167 | for (int noa = 0;(e = r.getChild(noa)) != null;noa++) |
---|
168 | { |
---|
169 | |
---|
170 | } |
---|
171 | } |
---|
172 | */ |
---|
173 | |
---|
174 | |
---|
175 | /** |
---|
176 | * This will set initial places for the x coord of the nodes. |
---|
177 | * @param start The `number for the first group to start on (I think). |
---|
178 | */ |
---|
179 | private void xPlacer(int start) { |
---|
180 | //this can be one of a few x_placers (the first) |
---|
181 | //it will work by placing 1 space inbetween each node |
---|
182 | //ie the first at 0 the second at 1 and so on |
---|
183 | //then it will add to this value the place of the parent |
---|
184 | //node - half of the size |
---|
185 | //i will break this up into several functions |
---|
186 | //first the gap setter; |
---|
187 | //then the shifter |
---|
188 | //it will require a vector shift function added to the node class |
---|
189 | //i will write an additional shifter for the untangler |
---|
190 | //for its particular situation |
---|
191 | |
---|
192 | Node r; |
---|
193 | Edge e; |
---|
194 | if (m_groupNum > 0) { |
---|
195 | m_groups[0].m_p.setCenter(0); |
---|
196 | for (int noa = start;noa < m_groupNum;noa++) { |
---|
197 | int nob,alter =0; |
---|
198 | double c = m_groups[noa].m_gap; |
---|
199 | r = m_groups[noa].m_p; |
---|
200 | for (nob = 0;(e = r.getChild(nob)) != null;nob++) { |
---|
201 | if (e.getTarget().getParent(0) == e) { |
---|
202 | e.getTarget().setCenter(nob * c); |
---|
203 | } |
---|
204 | else { |
---|
205 | alter++; |
---|
206 | } |
---|
207 | } |
---|
208 | m_groups[noa].m_size = (nob - 1 - alter) * c; |
---|
209 | xShift(noa); |
---|
210 | } |
---|
211 | } |
---|
212 | } |
---|
213 | |
---|
214 | /** |
---|
215 | * This will shift a group of nodes to be aligned under their parent. |
---|
216 | * @param n The group number to shift |
---|
217 | */ |
---|
218 | private void xShift(int n) { |
---|
219 | Edge e; |
---|
220 | Node r = m_groups[n].m_p; |
---|
221 | double h = m_groups[n].m_size / 2; |
---|
222 | double c = m_groups[n].m_p.getCenter(); |
---|
223 | double m = c - h; |
---|
224 | m_groups[n].m_left = m; |
---|
225 | m_groups[n].m_right = c + h; |
---|
226 | |
---|
227 | for (int noa = 0;(e = r.getChild(noa)) != null;noa++) { |
---|
228 | if (e.getTarget().getParent(0) == e) { |
---|
229 | e.getTarget().adjustCenter(m); |
---|
230 | } |
---|
231 | } |
---|
232 | } |
---|
233 | |
---|
234 | /** |
---|
235 | * This scales all the x values to be between 0 and 1. |
---|
236 | */ |
---|
237 | private void scaleByMax() { |
---|
238 | //ammendment to what i may have commented before |
---|
239 | //this takes the lowest x and highest x and uses that as the scaling |
---|
240 | //factor |
---|
241 | double l_x = 5000,h_x = -5000; |
---|
242 | for (int noa = 0;noa < m_groupNum;noa++) { |
---|
243 | if (l_x > m_groups[noa].m_left) { |
---|
244 | l_x = m_groups[noa].m_left; |
---|
245 | } |
---|
246 | |
---|
247 | if (h_x < m_groups[noa].m_right) { |
---|
248 | h_x = m_groups[noa].m_right; |
---|
249 | } |
---|
250 | } |
---|
251 | |
---|
252 | Edge e; |
---|
253 | Node r,s; |
---|
254 | double m_scale = h_x - l_x + 1; |
---|
255 | if (m_groupNum > 0) { |
---|
256 | r = m_groups[0].m_p; |
---|
257 | r.setCenter((r.getCenter() - l_x) / m_scale); |
---|
258 | //System.out.println("from scaler " + l_x + " " + m_scale); |
---|
259 | for (int noa = 0; noa < m_groupNum;noa++) { |
---|
260 | r = m_groups[noa].m_p; |
---|
261 | for (int nob = 0;(e = r.getChild(nob)) != null;nob++) { |
---|
262 | s = e.getTarget(); |
---|
263 | if (s.getParent(0) == e) { |
---|
264 | s.setCenter((s.getCenter() - l_x) / m_scale); |
---|
265 | } |
---|
266 | } |
---|
267 | } |
---|
268 | } |
---|
269 | } |
---|
270 | |
---|
271 | /** |
---|
272 | * This scales the x values to between 0 and 1 for each individual line |
---|
273 | * rather than doing them all at once. |
---|
274 | */ |
---|
275 | private void scaleByInd() { |
---|
276 | //ammendment to what i may have commented before |
---|
277 | //this takes the lowest x and highest x on each line and uses that for |
---|
278 | //the line in question |
---|
279 | double l_x,h_x; |
---|
280 | |
---|
281 | Edge e; |
---|
282 | Node r,s; |
---|
283 | r = m_groups[0].m_p; |
---|
284 | r.setCenter(.5); |
---|
285 | double m_scale; |
---|
286 | for (int noa = 0;noa < m_levelNum;noa++) { |
---|
287 | l_x = m_groups[m_levels[noa].m_start].m_left; |
---|
288 | h_x = m_groups[m_levels[noa].m_end].m_right; |
---|
289 | m_scale = h_x - l_x + 1; |
---|
290 | for (int nob = m_levels[noa].m_start; nob <= m_levels[noa].m_end;nob++) { |
---|
291 | r = m_groups[nob].m_p; |
---|
292 | for (int noc = 0;(e = r.getChild(noc)) != null;noc++) { |
---|
293 | s = e.getTarget(); |
---|
294 | if (s.getParent(0) == e) { |
---|
295 | s.setCenter((s.getCenter() - l_x) / m_scale); |
---|
296 | } |
---|
297 | } |
---|
298 | } |
---|
299 | } |
---|
300 | } |
---|
301 | |
---|
302 | /** |
---|
303 | * This untangles the nodes so that they will will fall on the correct |
---|
304 | * side of the other nodes along their row. |
---|
305 | */ |
---|
306 | private void untangle2() { |
---|
307 | Ease a; |
---|
308 | Edge e; |
---|
309 | Node r,nf = null,ns = null,mark; |
---|
310 | int l = 0,times = 0; |
---|
311 | int f,s,tf = 0,ts = 0,pf,ps; |
---|
312 | while ((a = overlap(l)) != null) { |
---|
313 | times++; |
---|
314 | //System.out.println("from untang 2 " + group_num); |
---|
315 | f = a.m_place; |
---|
316 | s = a.m_place + 1; |
---|
317 | while (f != s) { |
---|
318 | a.m_lev--; |
---|
319 | tf = f; |
---|
320 | ts = s; |
---|
321 | f = m_groups[f].m_pg; |
---|
322 | s = m_groups[s].m_pg; |
---|
323 | } |
---|
324 | l = a.m_lev; |
---|
325 | pf = 0; |
---|
326 | ps = 0; |
---|
327 | r = m_groups[f].m_p; |
---|
328 | mark = m_groups[tf].m_p; |
---|
329 | nf = null; |
---|
330 | ns = null; |
---|
331 | for (int noa = 0; nf != mark;noa++) { |
---|
332 | pf++; |
---|
333 | nf = r.getChild(noa).getTarget(); |
---|
334 | } |
---|
335 | mark = m_groups[ts].m_p; |
---|
336 | for (int noa = pf; ns != mark;noa++) { |
---|
337 | ps++; //the number of gaps between the two nodes |
---|
338 | ns = r.getChild(noa).getTarget(); |
---|
339 | } |
---|
340 | //m_groups[f].gap = |
---|
341 | // Math.ceil((a.amount / (double)ps) + m_groups[f].gap); |
---|
342 | //note for this method i do not need the group gap ,but i will leave |
---|
343 | //it for the other methods; |
---|
344 | Vector o_pos = new Vector(20,10); |
---|
345 | for (int noa = 0;(e = r.getChild(noa)) != null;noa++) { |
---|
346 | if (e.getTarget().getParent(0) == e) { |
---|
347 | Double tem = new Double(e.getTarget().getCenter()); |
---|
348 | o_pos.addElement(tem); |
---|
349 | } |
---|
350 | } |
---|
351 | |
---|
352 | pf--; |
---|
353 | double inc = a.m_amount / (double)ps; |
---|
354 | for (int noa = 0;(e = r.getChild(noa)) != null;noa++) { |
---|
355 | ns = e.getTarget(); |
---|
356 | if (ns.getParent(0) == e) { |
---|
357 | if (noa > pf + ps) { |
---|
358 | ns.adjustCenter(a.m_amount); |
---|
359 | } |
---|
360 | else if (noa > pf) { |
---|
361 | ns.adjustCenter(inc * (double)(noa - pf)); |
---|
362 | } |
---|
363 | } |
---|
364 | } |
---|
365 | |
---|
366 | nf = r.getChild(0).getTarget(); |
---|
367 | inc = ns.getCenter() - nf.getCenter(); |
---|
368 | m_groups[f].m_size = inc; |
---|
369 | m_groups[f].m_left = r.getCenter() - inc / 2; |
---|
370 | m_groups[f].m_right = m_groups[f].m_left + inc; |
---|
371 | inc = m_groups[f].m_left - nf.getCenter(); |
---|
372 | |
---|
373 | double shift; |
---|
374 | int g_num = 0; |
---|
375 | for (int noa = 0;(e = r.getChild(noa)) != null;noa++) { |
---|
376 | ns = e.getTarget(); |
---|
377 | if (ns.getParent(0) == e) { |
---|
378 | ns.adjustCenter(inc); |
---|
379 | shift = ns.getCenter() - |
---|
380 | ((Double)o_pos.elementAt(noa)).doubleValue(); |
---|
381 | if (ns.getChild(0) != null) { |
---|
382 | moveSubtree(m_groups[f].m_start + g_num,shift); |
---|
383 | g_num++; |
---|
384 | } |
---|
385 | } |
---|
386 | //ns.adjustCenter(-shift); |
---|
387 | } |
---|
388 | //zero_offset(r); |
---|
389 | |
---|
390 | //x_placer(f); |
---|
391 | } |
---|
392 | } |
---|
393 | |
---|
394 | |
---|
395 | /** |
---|
396 | * This will recursively shift a sub there to be centered about |
---|
397 | * a particular value. |
---|
398 | * @param n The first group in the sub tree. |
---|
399 | * @param o The point to start shifting the subtree. |
---|
400 | */ |
---|
401 | private void moveSubtree(int n,double o) { |
---|
402 | Edge e; |
---|
403 | Node r = m_groups[n].m_p; |
---|
404 | for (int noa = 0;(e = r.getChild(noa)) != null;noa++) { |
---|
405 | if (e.getTarget().getParent(0) == e) { |
---|
406 | e.getTarget().adjustCenter(o); |
---|
407 | } |
---|
408 | } |
---|
409 | m_groups[n].m_left += o; |
---|
410 | m_groups[n].m_right += o; |
---|
411 | if (m_groups[n].m_start != -1) { |
---|
412 | for (int noa = m_groups[n].m_start;noa <= m_groups[n].m_end;noa++) { |
---|
413 | moveSubtree(noa,o); |
---|
414 | } |
---|
415 | } |
---|
416 | } |
---|
417 | |
---|
418 | |
---|
419 | /** |
---|
420 | * This will untangle the nodes in the tree so that they fall on the |
---|
421 | * correct side of each other. |
---|
422 | */ |
---|
423 | private void untangle() { |
---|
424 | Ease a; |
---|
425 | Edge e; |
---|
426 | Node r,nf = null,ns = null,mark; |
---|
427 | int l = 0,times = 0; |
---|
428 | int f,s,tf = 0,ts = 0,pf,ps; |
---|
429 | while ((a = overlap(l)) != null) { |
---|
430 | times++; |
---|
431 | //System.out.println(group_num); |
---|
432 | f = a.m_place; |
---|
433 | s = a.m_place + 1; |
---|
434 | while (f != s) { |
---|
435 | a.m_lev--; |
---|
436 | tf = f; |
---|
437 | ts = s; |
---|
438 | f = m_groups[f].m_pg; |
---|
439 | s = m_groups[s].m_pg; |
---|
440 | } |
---|
441 | l = a.m_lev; |
---|
442 | pf = 0; |
---|
443 | ps = 0; |
---|
444 | r = m_groups[f].m_p; |
---|
445 | mark = m_groups[tf].m_p; |
---|
446 | nf = null; |
---|
447 | ns = null; |
---|
448 | for (int noa = 0; nf != mark;noa++) { |
---|
449 | pf++; |
---|
450 | nf = r.getChild(noa).getTarget(); |
---|
451 | } |
---|
452 | mark = m_groups[ts].m_p; |
---|
453 | for (int noa = pf; ns != mark;noa++) { |
---|
454 | ps++; //the number of gaps between the two nodes |
---|
455 | ns = r.getChild(noa).getTarget(); |
---|
456 | } |
---|
457 | m_groups[f].m_gap = |
---|
458 | Math.ceil((a.m_amount / (double)ps) + m_groups[f].m_gap); |
---|
459 | |
---|
460 | xPlacer(f); |
---|
461 | } |
---|
462 | } |
---|
463 | |
---|
464 | /** |
---|
465 | * This will find an overlap and then return information about that overlap |
---|
466 | * @param l The level to start on. |
---|
467 | * @return null if there was no overlap , otherwise an object containing |
---|
468 | * the group number that overlaps (only need one) how much they overlap by, |
---|
469 | * and the level they overlap on. |
---|
470 | */ |
---|
471 | private Ease overlap(int l) { |
---|
472 | Ease a = new Ease(); |
---|
473 | for (int noa = l;noa < m_levelNum;noa++) { |
---|
474 | for (int nob = m_levels[noa].m_start;nob < m_levels[noa].m_end;nob++) { |
---|
475 | a.m_amount = m_groups[nob].m_right - m_groups[nob+1].m_left + 2; |
---|
476 | //System.out.println(m_groups[nob].m_right + " + " + |
---|
477 | // m_groups[nob+1].m_left + " = " + a.amount); |
---|
478 | if (a.m_amount >= 0) { |
---|
479 | a.m_amount++; |
---|
480 | a.m_lev = noa; |
---|
481 | a.m_place = nob; |
---|
482 | return a; |
---|
483 | } |
---|
484 | } |
---|
485 | } |
---|
486 | return null; |
---|
487 | } |
---|
488 | |
---|
489 | /* private int count_m_groups(Node r,int l) |
---|
490 | { |
---|
491 | Edge e; |
---|
492 | if (r.getChild(0) != null) |
---|
493 | { |
---|
494 | l++; |
---|
495 | } |
---|
496 | for (int noa = 0;(e = r.getChild(noa)) != null;noa++) |
---|
497 | { |
---|
498 | l = count_groups(e.getTarget(),l); |
---|
499 | } |
---|
500 | |
---|
501 | return l; |
---|
502 | } |
---|
503 | */ |
---|
504 | |
---|
505 | /** |
---|
506 | * This function sets up the height of each node, and also fills the |
---|
507 | * levels array with information about what the start and end groups on that |
---|
508 | * level are. |
---|
509 | */ |
---|
510 | private void yPlacer() { |
---|
511 | //note this places the y height and sets up the levels array |
---|
512 | double changer = m_yRatio; |
---|
513 | int lev_place = 0; |
---|
514 | if (m_groupNum > 0) { |
---|
515 | m_groups[0].m_p.setTop(m_yRatio); |
---|
516 | m_levels[0].m_start = 0; |
---|
517 | |
---|
518 | for (int noa = 0;noa < m_groupNum;noa++) { |
---|
519 | if (m_groups[noa].m_p.getTop() != changer) { |
---|
520 | m_levels[lev_place].m_end = noa - 1; |
---|
521 | lev_place++; |
---|
522 | m_levels[lev_place].m_start = noa; |
---|
523 | changer = m_groups[noa].m_p.getTop(); |
---|
524 | } |
---|
525 | nodeY(m_groups[noa].m_p); |
---|
526 | } |
---|
527 | m_levels[lev_place].m_end = m_groupNum - 1; |
---|
528 | } |
---|
529 | } |
---|
530 | |
---|
531 | /** |
---|
532 | * This will set all of the children node of a particular node to their |
---|
533 | * height. |
---|
534 | * @param r The parent node of the children to set their height. |
---|
535 | */ |
---|
536 | private void nodeY(Node r) { |
---|
537 | Edge e; |
---|
538 | double h = r.getTop() + m_yRatio; |
---|
539 | for (int noa = 0;(e = r.getChild(noa)) != null;noa++) { |
---|
540 | if (e.getTarget().getParent(0) == e) { |
---|
541 | e.getTarget().setTop(h); |
---|
542 | if (!e.getTarget().getVisible()) { |
---|
543 | //System.out.println("oh bugger"); |
---|
544 | } |
---|
545 | } |
---|
546 | } |
---|
547 | } |
---|
548 | |
---|
549 | /** |
---|
550 | * This starts to create the information about the sibling groups. |
---|
551 | * As more groups are created the for loop in this will check those groups |
---|
552 | * for lower groups. |
---|
553 | * @param r The top node. |
---|
554 | */ |
---|
555 | private void groupBuild(Node r) { |
---|
556 | if (m_groupNum > 0) { |
---|
557 | m_groupNum = 0; |
---|
558 | m_groups[0].m_p = r; |
---|
559 | m_groupNum++; |
---|
560 | //note i need to count up the num of groups first |
---|
561 | //woe is me |
---|
562 | for (int noa = 0;noa < m_groupNum ;noa++) { |
---|
563 | groupFind(m_groups[noa].m_p,noa); |
---|
564 | } |
---|
565 | } |
---|
566 | } |
---|
567 | |
---|
568 | /** |
---|
569 | * This is called to build the rest of the grouping information. |
---|
570 | * @param r The parent of the group. |
---|
571 | * @param pg The number for the parents group. |
---|
572 | */ |
---|
573 | private void groupFind(Node r,int pg) { |
---|
574 | Edge e; |
---|
575 | boolean first = true; |
---|
576 | for (int noa = 0;(e = r.getChild(noa)) != null;noa++) { |
---|
577 | if (e.getTarget().getParent(0) == e) { |
---|
578 | if (e.getTarget().getChild(0) != null && e.getTarget().getCVisible()) { |
---|
579 | if (first) { |
---|
580 | m_groups[pg].m_start = m_groupNum; |
---|
581 | first = false; |
---|
582 | } |
---|
583 | m_groups[pg].m_end = m_groupNum; |
---|
584 | m_groups[m_groupNum].m_p = e.getTarget(); |
---|
585 | m_groups[m_groupNum].m_pg = pg; |
---|
586 | m_groups[m_groupNum].m_id = m_groupNum; //just in case I ever need |
---|
587 | //this info |
---|
588 | m_groupNum++; |
---|
589 | } |
---|
590 | } |
---|
591 | } |
---|
592 | } |
---|
593 | |
---|
594 | |
---|
595 | //note these three classes are only to help organise the data and are |
---|
596 | //inter related between each other and this placer class |
---|
597 | //so don't mess with them or try to use them somewhere else |
---|
598 | //(because that would be a mistake and I would pity you) |
---|
599 | |
---|
600 | |
---|
601 | /** |
---|
602 | * Inner class for containing the level data. |
---|
603 | */ |
---|
604 | private class Level { |
---|
605 | /** The number for the group on the left of this level. */ |
---|
606 | public int m_start; |
---|
607 | /** The number for the group on the right of this level. */ |
---|
608 | public int m_end; |
---|
609 | |
---|
610 | /** These two params would appear to not be used. */ |
---|
611 | public int m_left; |
---|
612 | public int m_right; |
---|
613 | } |
---|
614 | |
---|
615 | /** |
---|
616 | * Inner class for containing the grouping data. |
---|
617 | */ |
---|
618 | private class Group { |
---|
619 | /** The parent node of this group. */ |
---|
620 | public Node m_p; |
---|
621 | |
---|
622 | /** The group number for the parent of this group. */ |
---|
623 | public int m_pg; |
---|
624 | |
---|
625 | /** The gap size for the distance between the nodes in this group. */ |
---|
626 | public double m_gap; |
---|
627 | |
---|
628 | /** The leftmost position of this group. */ |
---|
629 | public double m_left; |
---|
630 | |
---|
631 | /** The rightmost position of this group. */ |
---|
632 | public double m_right; |
---|
633 | |
---|
634 | /** The size of this group. */ |
---|
635 | public double m_size; |
---|
636 | |
---|
637 | /** The start node of this group. */ |
---|
638 | public int m_start; |
---|
639 | |
---|
640 | /** The end node of this group. */ |
---|
641 | public int m_end; |
---|
642 | |
---|
643 | /** The group number for this group. (may not be used!?). */ |
---|
644 | public int m_id; |
---|
645 | } |
---|
646 | |
---|
647 | /** |
---|
648 | * An inner class used to report information about any tangles found. |
---|
649 | */ |
---|
650 | private class Ease { |
---|
651 | /** The number of the group on the left of the tangle. */ |
---|
652 | public int m_place; |
---|
653 | /** The distance they were tangled. */ |
---|
654 | public double m_amount; |
---|
655 | /** The level on which they were tangled. */ |
---|
656 | public int m_lev; |
---|
657 | } |
---|
658 | } |
---|
659 | |
---|
660 | |
---|
661 | |
---|
662 | |
---|
663 | |
---|
664 | |
---|
665 | |
---|
666 | |
---|
667 | |
---|
668 | |
---|
669 | |
---|
670 | |
---|
671 | |
---|
672 | |
---|