/*
* The GPLv3 licence :
* -----------------
* Copyright (c) 2009 Ricardo Dias
*
* This file is part of MuVis.
*
* MuVis is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* MuVis is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MuVis. If not, see <http://www.gnu.org/licenses/>.
*/
package muvis.view.main;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.util.Collections;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.Vector;
import net.bouthier.treemapSwing.*;
/**
* The TMAlgorithmDescOrder class implements a squarified treemap drawing
* algorithm, ordered by name DESC.
* See TMAlgorithmSquarified.java
*/
public class TMAlgorithmDescOrder
extends TMAlgorithm {
/**
* Draws the children of a node, by setting their drawing area first,
* dependant of the algorithm used.
*
* @param g the graphic context
* @param node the node whose children should be drawn
* @param axis the axis of separation
* @param level the level of deep
*/
protected void drawChildren(Graphics2D g,
TMNodeModelComposite node,
short axis,
int level) {
// Function AllocatePosition (s,r) {
// float d← sqrt(r.area / n);
// boolean isHorizontal← (r.width < r.height);
// List positions;
// for i←0to < n {
// if (isHorizontal) {
// x ←r.x + mod(i∗d, r.width);
// y ←r.y + f loor(i∗d/ r.width)∗d;
// } else {
// x ←r.x + f loor(i∗d/ r.height)∗d;
// y ←r.y + mod(i∗d, r.height);
// }
// positions.add(x,y);
// }
// sortByDistance(positions);
// for each node in s {
// node← positions(i++);
// }
// }
float pSize = node.getSize();
Rectangle pArea = node.getArea();
int x = pArea.x;
int y = pArea.y;
int width = pArea.width;
int height = pArea.height;
TMNodeModel child = null;
//Vector sortedChilds = new Vector();
if (pSize == 0.0f) {
return;
}
if ((width > borderLimit) && (height > borderLimit)) {
x += borderSize;
y += borderSize;
width -= borderSize * 2;
height -= borderSize * 2;
}
//ArrayList<TMNodeModel> sortedChilds = new ArrayList<TMNodeModel>();
Vector sortedChilds = new Vector();
for (Enumeration e = node.children(); e.hasMoreElements();) {
sortedChilds.add((TMNodeModel) e.nextElement());
}
Collections.sort(sortedChilds, new DescTMNodeComparator());
// sort child in decreasing size order
/*boolean isFirst = true;
for (Enumeration e = node.children(); e.hasMoreElements();) {
child = (TMNodeModel) e.nextElement();
float cSize = child.getSize();
if (isFirst) {
sortedChilds.add(child);
isFirst = false;
} else {
boolean childSorted = false;
TMNodeModel candidate = null;
for (int index = 0; index < sortedChilds.size(); index++) {
candidate = (TMNodeModel) sortedChilds.get(index);
float candidateSize = candidate.getSize();
if (candidateSize < cSize) {
sortedChilds.add(index, child);
childSorted = true;
break;
}
}
if (!childSorted) {
sortedChilds.add(child);
}
}
}*/
while (!sortedChilds.isEmpty()) {
child = (TMNodeModel) sortedChilds.remove(0);
Vector block = new Vector();
block.add(child);
float blockSize = child.getSize();
short blockAxis = HORIZONTAL;
if (width < height) {
blockAxis = VERTICAL;
}
float w = 0.0f;
float h = 0.0f;
if (blockAxis == HORIZONTAL) {
w = (blockSize / pSize) * width;
h = height;
} else {
w = width;
h = (blockSize / pSize) * height;
}
float ratio = ratio(w, h);
boolean blockDone = false;
while ((!sortedChilds.isEmpty()) && (!blockDone)) {
TMNodeModel candidate =
(TMNodeModel) sortedChilds.firstElement();
float newSize = candidate.getSize();
float newBlockSize = blockSize + newSize;
float newW = 0.0f;
float newH = 0.0f;
if (blockAxis == HORIZONTAL) {
newW = (newBlockSize / pSize) * width;
newH = (newSize / newBlockSize) * height;
} else {
newW = (newSize / newBlockSize) * width;
newH = (newBlockSize / pSize) * height;
}
float newRatio = ratio(newW, newH);
if (newRatio > ratio) {
blockDone = true;
} else {
sortedChilds.remove(0);
block.add(candidate);
ratio = newRatio;
blockSize = newBlockSize;
}
}
int childWidth = 0;
int childHeight = 0;
int childX = x;
int childY = y;
int maxX = x + width - 1;
int maxY = y + height - 1;
if (blockAxis == HORIZONTAL) {
childWidth = Math.round((blockSize / pSize) * width);
} else {
childHeight = Math.round((blockSize / pSize) * height);
}
float proportion = 0.0f;
float remaining = 0.0f;
for (Enumeration e = block.elements(); e.hasMoreElements();) {
child = (TMNodeModel) e.nextElement();
Rectangle cArea = child.getArea();
cArea.x = childX;
cArea.y = childY;
proportion = (child.getSize()) / blockSize;
if (e.hasMoreElements()) {
if (blockAxis == HORIZONTAL) {
float fHeight = proportion * height;
childHeight = Math.round(fHeight);
remaining += fHeight - childHeight;
if (remaining >= 1) {
childHeight += 1;
remaining -= 1;
} else if (remaining <= -1) {
childHeight -= 1;
remaining += 1;
}
childY += childHeight;
} else { // VERTICAL
float fWidth = proportion * width;
childWidth = Math.round(fWidth);
remaining += fWidth - childWidth;
if (remaining >= 1) {
childWidth += 1;
remaining -= 1;
} else if (remaining <= -1) {
childWidth -= 1;
remaining += 1;
}
childX += childWidth;
}
} else { // last element fills
if (blockAxis == HORIZONTAL) {
childHeight = (maxY - childY) + 1;
} else {
childWidth = (maxX - childX) + 1;
}
}
cArea.width = childWidth;
cArea.height = childHeight;
drawNodes(g, child, switchAxis(axis), (level + 1));
}
pSize -= blockSize;
if (blockAxis == HORIZONTAL) {
x += childWidth;
width -= childWidth;
} else {
y += childHeight;
height -= childHeight;
}
}
}
private float ratio(float w, float h) {
return Math.max((w / h), (h / w));
}
}
class DescTMNodeComparator implements Comparator<TMNodeModel>{
@Override
public int compare(TMNodeModel o1, TMNodeModel o2) {
String o1Str = o1.getTitle();
String o2Str = o2.getTitle();
int strCompare = o1Str.compareTo(o2Str);
int sizeCompare = 0;
if (o1.getSize() < o2.getSize()) sizeCompare = -1;
else if (o1.getSize() > o2.getSize()) sizeCompare = 1;
else sizeCompare = 0;
/*if (strCompare == -1){
if (sizeCompare == -1){
return 1;
}
else if (sizeCompare == 0){
return 1;
}
else return 0;
}
else if (strCompare == 1){
if (sizeCompare ==-1){
return 1;
}
else if (sizeCompare == 1){
return -1;
}
else return 0;
}
else return 0;*/
if (strCompare == 1) return -1;
else if (strCompare == -1) return 1;
else return 0;
}
}