package wordcloud.tree;
import wordcloud.Word;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
/**
* Created by kenny on 7/2/14.
*/
public class QuadTree {
private static class Node {
public final Word word;
public Node NE;
public Node SE;
public Node SW;
public Node NW;
private Node(final Word word) {
this.word = word;
}
}
private Node root;
public void add(final Word word) {
if(root == null) {
root = new Node(word);
return;
}
add(word, root);
}
private void add(final Word word, final Node node) {
if(word.equals(node.word)) { return; }
addByVertix(word, word.getX(), word.getY(), node);
addByVertix(word, word.getX() + word.getWidth(), word.getY(), node);
addByVertix(word, word.getX(), word.getY() + word.getHeight(), node);
addByVertix(word, word.getX() + word.getWidth(), word.getY() + word.getHeight(), node);
}
private void addByVertix(final Word word, int x2, int y2, Node node) {
final int x = node.word.getX();
final int y = node.word.getY();
if(x2 < x) {
if(y2 < y) {
if(node.NW == null) {
node.NW = new Node(word);
} else {
add(word, node.NW);
}
} else {
if(node.SW == null) {
node.SW = new Node(word);
} else {
add(word, node.SW);
}
}
} else {
if(y2 < y) {
if(node.NE == null) {
node.NE = new Node(word);
} else {
add(word, node.NE);
}
} else {
if(node.SE == null) {
node.SE = new Node(word);
} else {
add(word, node.SE);
}
}
}
}
public Set<Word> getNearby(final Word word) {
if(root == null) { return Collections.EMPTY_SET; }
final Set<Word> nearby = new HashSet<>();
getNearby(word, root, nearby);
return nearby;
}
private void getNearby(Word word, Node node, Set<Word> nearby) {
if(word.equals(node.word)) { return; }
if(node.word == null) { return; }
nearby.add(node.word);
getNearbyByVertix(word, word.getX(), word.getY(), node, nearby);
getNearbyByVertix(word, word.getX() + word.getWidth(), word.getY(), node, nearby);
getNearbyByVertix(word, word.getX(), word.getY() + word.getHeight(), node, nearby);
getNearbyByVertix(word, word.getX() + word.getWidth(), word.getY() + word.getHeight(), node, nearby);
}
private void getNearbyByVertix(Word word, int x2, int y2, Node node, Set<Word> nearby) {
final int x = node.word.getX();
final int y = node.word.getY();
if(x2 < x) {
if(y2 < y) {
if(node.NW != null) {
getNearby(word, node.NW, nearby);
}
} else {
if(node.SW != null) {
getNearby(word, node.SW, nearby);
}
}
} else {
if(y2 < y) {
if(node.NE != null) {
getNearby(word, node.NE, nearby);
}
} else {
if(node.SE != null) {
getNearby(word, node.SE, nearby);
}
}
}
}
}