Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.jungrapht.samples.rtree.RTreeVisualizer Maven / Gradle / Ivy
package org.jungrapht.samples.rtree;
import java.awt.*;
import java.awt.event.ItemEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import javax.swing.*;
import org.jungrapht.visualization.spatial.rtree.Bounded;
import org.jungrapht.visualization.spatial.rtree.InnerNode;
import org.jungrapht.visualization.spatial.rtree.LeafNode;
import org.jungrapht.visualization.spatial.rtree.Node;
import org.jungrapht.visualization.spatial.rtree.RStarLeafSplitter;
import org.jungrapht.visualization.spatial.rtree.RStarSplitter;
import org.jungrapht.visualization.spatial.rtree.RTree;
import org.jungrapht.visualization.spatial.rtree.SplitterContext;
import org.jungrapht.visualization.spatial.rtree.TreeNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* A visualization of the R-Tree structure. users can add random elements, elements at mouse-click
* location, or 2000 randomly generated elements. The structure of the R-Tree is also drawn
*
* @author Tom Nelson
*/
public class RTreeVisualizer extends JPanel {
private static final Logger log = LoggerFactory.getLogger(RTreeVisualizer.class);
private final int INITIAL_WIDTH = 600;
private final int INITIAL_HEIGHT = 600;
SplitterContext splitterContext =
SplitterContext.of(new RStarLeafSplitter<>(), new RStarSplitter<>());
RTree rTree = RTree.create();
int count;
boolean running;
public RTreeVisualizer() {
setBackground(Color.white);
setLayout(new BorderLayout());
JToggleButton timerAdd = new JToggleButton("Timed add");
timerAdd.addItemListener( // who cares
this::itemStateChanged);
JButton addStuff = new JButton("Add something");
addStuff.addActionListener(e -> addRandomShape());
JPanel drawingPane =
new JPanel() {
public Dimension getPreferredSize() {
return new Dimension(INITIAL_WIDTH, INITIAL_HEIGHT);
}
@Override
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
Color oldColor = g2d.getColor();
Map map = getGridInColor();
for (Map.Entry entry : map.entrySet()) {
g2d.setColor(entry.getValue());
g2d.draw(entry.getKey());
}
g2d.setColor(oldColor);
}
};
JButton addLots = new JButton("Add Many");
addLots.addActionListener(e -> addMany());
JButton bulkAddLots = new JButton("Bulk Add");
bulkAddLots.addActionListener(e -> bulkInsertMany());
drawingPane.addMouseListener(
new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
super.mouseClicked(e);
if (SwingUtilities.isRightMouseButton(e)) {
Object o = rTree.getPickedObject(e.getPoint());
rTree = RTree.remove(rTree, o);
log.trace("after removing {} rtree:{}", o, rTree);
repaint();
} else {
addShapeAt(e.getPoint());
}
repaint();
}
});
JButton samePoint = new JButton("Add Same");
samePoint.addActionListener(e -> addShapeAt(new Point2D.Double(200, 200)));
final java.util.List> goners = new ArrayList<>();
JButton removeForReinsert = new JButton("Remove for re-insert");
removeForReinsert.addActionListener(
e -> {
goners.clear();
rTree = RTree.removeForReinsert(rTree, goners);
repaint();
});
JButton reinsertThese = new JButton("Reinsert them");
reinsertThese.addActionListener(
e -> {
rTree = RTree.addAll(rTree, splitterContext, goners);
repaint();
});
JButton reinsert = new JButton("Re-insert");
reinsert.addActionListener(
e -> {
rTree = RTree.reinsert(rTree, splitterContext);
repaint();
});
JButton clear = new JButton("clear");
clear.addActionListener(
e -> {
rTree = RTree.create();
repaint();
});
JPanel controls = new JPanel();
controls.add(timerAdd);
controls.add(addStuff);
controls.add(addLots);
controls.add(bulkAddLots);
controls.add(clear);
controls.add(samePoint);
controls.add(reinsert);
controls.add(removeForReinsert);
controls.add(reinsertThese);
add(drawingPane);
add(controls, BorderLayout.SOUTH);
}
private void addRandomShape() {
double width = 10;
double height = 10;
double x = Math.random() * getWidth() - width;
double y = Math.random() * getHeight() - height;
Rectangle2D r = new Rectangle2D.Double(x, y, width, height);
rTree = RTree.add(rTree, splitterContext, "N" + count++, r);
repaint();
}
private void addMany() {
for (int i = 0; i < 2000; i++) {
double width = 4;
double height = 4;
double x = Math.random() * getWidth() - width;
double y = Math.random() * getHeight() - height;
Rectangle2D r = new Rectangle2D.Double(x, y, width, height);
rTree = RTree.add(rTree, splitterContext, "N" + count++, r);
checkBounds(rTree);
// repaint();
}
repaint();
}
private void bulkInsertMany() {
java.util.List> list = new ArrayList<>();
for (int i = 0; i < 100; i++) {
double width = 4;
double height = 4;
double x = Math.random() * getWidth() - width;
double y = Math.random() * getHeight() - height;
Rectangle2D r = new Rectangle2D.Double(x, y, width, height);
list.add(new AbstractMap.SimpleEntry("N" + count++, r));
}
rTree = RTree.bulkAdd(rTree, splitterContext, list);
checkBounds(rTree);
repaint();
}
private void addShapeAt(Point2D p) {
double width = 10;
double height = 10;
Rectangle2D r =
new Rectangle2D.Double(p.getX() - width / 2, p.getY() - height / 2, width, height);
rTree = RTree.add(rTree, splitterContext, "N" + count++, r);
log.trace("after adding {} at {}, rtree:{}", "N" + (count - 1), p, rTree);
checkBounds(rTree);
repaint();
}
private void checkBounds(RTree> tree) {
checkBounds(tree.getRoot().get());
}
private Rectangle2D getBounds(Collection extends Bounded> nodes) {
Rectangle2D bounds = null;
for (Bounded b : nodes) {
if (bounds == null) bounds = b.getBounds();
else {
bounds = bounds.createUnion(b.getBounds());
}
}
return bounds;
}
private void checkBounds(InnerNode> node) {
if (!node.getBounds().equals(getBounds(node.getChildren()))) {
log.error("bounds not equal \n{} != \n{}", node.getBounds(), getBounds(node.getChildren()));
}
}
private void checkBounds(Node> node) {
if (node instanceof InnerNode) {
checkBounds((InnerNode) node);
} else if (node instanceof LeafNode) {
log.trace("leafVertex: {}", node);
}
}
public static void main(String[] args) {
JFrame f = new JFrame();
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.getContentPane().add(new RTreeVisualizer());
f.pack();
f.setVisible(true);
}
private Map getGridInColor() {
Optional> maybeRoot = rTree.getRoot();
return maybeRoot.map(this::getGridFor).orElse(Collections.emptyMap());
}
private Map getGridFor(TreeNode parent) {
Map map = new HashMap<>();
if (parent instanceof LeafNode) {
LeafNode leafParent = (LeafNode) parent;
// get a color from the hashcode of this parent, and use that color for the parent and its children
String hashString = "" + parent.hashCode();
try {
String lastSix = hashString.substring(hashString.length() - 6);
int rgb = Integer.parseInt(lastSix, 16);
Color color = new Color(rgb);
map.put(parent.getBounds(), color);
for (Shape kidShape : leafParent.collectGrids(new ArrayList<>())) {
map.put(kidShape.getBounds(), color);
}
} catch (Exception ex) {
log.info("hashString was {}", hashString);
}
} else {
map.put(parent.getBounds(), Color.pink);
for (TreeNode child : parent.getChildren()) {
map.putAll(getGridFor(child));
}
}
return map;
}
private void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
running = true;
Thread timerAddThread =
new Thread(
() -> {
while (running) {
SwingUtilities.invokeLater(this::addRandomShape);
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
// who cares
}
}
});
timerAddThread.start();
} else {
running = false;
}
}
}