--- /dev/null
+package org.feistymeow.algorithms;
+
+
+//hmmm: move to better folder path.
+
+// inspired by http://pages.cs.wisc.edu/~cs367-1/readings/Binary-Search-Trees/
+
+/**
+ * The type of node held in our binary search tree.
+ */
+class TreeNode<K, V>
+{
+ private K key;
+ private V value;
+ private TreeNode<K, V> left, right;
+
+ public TreeNode(K key, V value, TreeNode<K, V> left, TreeNode<K, V> right) {
+ this.key = key;
+ this.value = value;
+ this.left = left;
+ this.right = right;
+ }
+
+ public K getKey() { return key; }
+ public V getValue() { return value; }
+
+
+ public TreeNode<K, V> getLeft() { return left; }
+ public TreeNode<K, V> getRight() { return right; }
+
+ public void setKey(K newK) { key = newK; }
+ public void setLeft(TreeNode<K, V> newL) { left = newL; }
+ public void setRight(TreeNode<K, V> newR) { right = newR; }
+
+ public void setValue(V newV) { value = newV; }
+}
+
+class DuplicateException extends RuntimeException
+{
+ private static final long serialVersionUID = 1L;
+ DuplicateException() {}
+}
+
+/**
+ * A binary search tree implementation.
+ *
+ * Insert, Delete and Search are done in O(n log(n)) time.
+ */
+public class BinarySearchTree<K extends Comparable<K>, V>
+{
+ private TreeNode<K, V> root; // ptr to the root of the BinarySearchTree
+
+ public BinarySearchTree() { root = null; }
+
+
+ // add key and associated value to this BinarySearchTree;
+ // error if key is already there
+ public void insert(K key, V value) throws DuplicateException {
+ root = insert(root, value, key);
+ }
+
+ private TreeNode<K, V> insert(TreeNode<K, V> n, V value, K key) throws DuplicateException {
+ if (n == null) {
+ return new TreeNode<K, V>(key, value, null, null);
+ }
+
+ if (n.getKey().equals(key)) {
+ throw new DuplicateException();
+ }
+
+ if (key.compareTo(n.getKey()) < 0) {
+ // add key to the left subtree
+ n.setLeft( insert(n.getLeft(), value, key) );
+ return n;
+ }
+
+ else {
+ // add key to the right subtree
+ n.setRight( insert(n.getRight(), value, key) );
+ return n;
+ }
+ }
+
+ // remove the node containing key from this BinarySearchTree if it is there;
+ // otherwise, do nothing
+ public void delete(K key) {
+ root = delete(root, key);
+ }
+
+
+ private K smallest(TreeNode<K, V> n)
+ // precondition: n is not null
+ // postcondition: return the smallest value in the subtree rooted at n
+
+ {
+ if (n.getLeft() == null) {
+ return n.getKey();
+ } else {
+ return smallest(n.getLeft());
+ }
+ }
+
+ private TreeNode<K, V> delete(TreeNode<K, V> n, K key)
+ {
+ if (n == null) {
+ return null;
+ }
+
+ if (key.equals(n.getKey())) {
+
+ if (n.getLeft() == null && n.getRight() == null) {
+ return null;
+ }
+ if (n.getLeft() == null) {
+ return n.getRight();
+ }
+ if (n.getRight() == null) {
+ return n.getLeft();
+ }
+
+ // if we get here, then n has 2 children
+ K smallVal = smallest(n.getRight());
+ n.setKey(smallVal);
+ n.setRight( delete(n.getRight(), smallVal) );
+ return n;
+ }
+
+ else if (key.compareTo(n.getKey()) < 0) {
+ n.setLeft( delete(n.getLeft(), key) );
+ return n;
+ }
+
+ else {
+ n.setRight( delete(n.getRight(), key) );
+ return n;
+ }
+ }
+
+
+ // if key is in this BinarySearchTree, return its associated value; otherwise, return null
+ public boolean lookup(K key) {
+ return lookup(root, key);
+ }
+
+ private boolean lookup(TreeNode<K, V> n, K key) {
+ if (n == null) {
+ return false;
+ }
+
+ if (n.getKey().equals(key)) {
+ return true;
+ }
+
+ if (key.compareTo(n.getKey()) < 0) {
+ // key < this node's key; look in left subtree
+ return lookup(n.getLeft(), key);
+ }
+
+ else {
+ // key > this node's key; look in right subtree
+ return lookup(n.getRight(), key);
+ }
+ }
+
+// // print the values in this BinarySearchTree in sorted order (to p)
+// public void print(PrintStream p) {
+//
+// }
+}
+
--- /dev/null
+package org.feistymeow.algorithms;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.Vector;
+
+import org.feistymeow.algorithms.RectangleIntersector.SortedElement;
+import org.feistymeow.algorithms.RectangleIntersector.SortedElementComparator;
+
+/**
+ * reports if any two rectangles in a list intersect. uses screen coordinates.
+ */
+public class RectangleIntersector
+{
+ public RectangleIntersector()
+ {
+
+ }
+
+ public static class Point
+ {
+ Point(double x, double y)
+ {
+ this.x = x;
+ this.y = y;
+ }
+
+ double x, y;
+ }
+
+ public static class Rectangle
+ {
+ Rectangle(Point ul, Point lr)
+ {
+ this.ul = ul;
+ this.lr = lr;
+ }
+
+ Point ul, lr;
+ }
+
+ public static boolean doesPointOverlap(Point p, Rectangle r)
+ {
+ return p.x <= r.lr.x && p.x >= r.ul.x && p.y <= r.lr.y && p.y >= r.ul.y;
+ }
+
+ public static boolean doRectanglesOverlap(Rectangle r1, Rectangle r2)
+ {
+ return doesPointOverlap(r1.ul, r2) || doesPointOverlap(r1.lr, r2) || doesPointOverlap(r2.ul, r1) || doesPointOverlap(r2.lr, r1);
+ }
+
+ /**
+ * find any overlapping pair of rectangles in the list provided.
+ */
+ public static Vector<Rectangle> findOverlapBruteForce(Vector<Rectangle> list)
+ {
+ // terrible brute force algorithm below.
+ for (int i = 0; i < list.size(); i++) {
+ for (int j = i; j < list.size(); j++) {
+ if (doRectanglesOverlap(list.get(i), list.get(j))) {
+ ArrayList<Rectangle> toReturn = new ArrayList<Rectangle>();
+ toReturn.add(list.get(i));
+ toReturn.add(list.get(j));
+ }
+ }
+ }
+ return null;
+ }
+
+ public static class SortedElement
+ {
+ double value; // the key.
+ boolean lowerEdge; // is this the left side?
+ Rectangle source; // where did this value come from.
+
+ public SortedElement(double value, boolean lowerEdge, Rectangle source)
+ {
+ this.value = value;
+ this.lowerEdge = lowerEdge;
+ this.source = source;
+ }
+ }
+
+ public static class SortedElementComparator implements Comparator<SortedElement>
+ {
+ @Override
+ public int compare(SortedElement k1, SortedElement k2)
+ {
+ SortedElementKey key1 = new SortedElementKey(k1.value);
+ return key1.compareTo(new SortedElementKey(k2.value));
+ }
+
+ Double value;
+ }
+
+ public static class SortedElementKey implements Comparable<SortedElementKey>
+ {
+ public SortedElementKey(double key)
+ {
+ this.key = key;
+ }
+
+ @Override
+ public int compareTo(SortedElementKey k2)
+ {
+ return (key == k2.key) ? 0 : (key < k2.key) ? -1 : 1;
+ }
+
+ double key;
+ }
+
+ /**
+ * find any overlapping pair of rectangles in the list provided.
+ *
+ * this is classed as a good answer... if it works.
+ */
+ public static Vector<Rectangle> findOverlap(Vector<Rectangle> list)
+ {
+ // first phase, produce a sorted list of the x coordinates of the rectangles.
+ // this completes in O(n log(n)) time.
+ ArrayList<SortedElement> xEdges = new ArrayList<SortedElement>();
+ for (Rectangle r : list) {
+ xEdges.add(new SortedElement(r.lr.x, true, r));
+ xEdges.add(new SortedElement(r.ul.x, false, r));
+ }
+ // we're assuming this is an efficient sort; i've heard rumors that it's a heapsort.
+ // if so we're good. if not, we'd write our own heapsort (see feisty meow nucleus sorts.h).
+ xEdges.sort(new SortedElementComparator());
+
+ // second phase, crawl across the sorted list and build up a binary search tree
+ // with the y coordinates from the rectangles. we will use this to check for
+ // intersections.
+ BinarySearchTree<SortedElementKey, SortedElement> bst = new BinarySearchTree<SortedElementKey, SortedElement>();
+
+ for (SortedElement scanner : xEdges) {
+ Rectangle source = scanner.source;
+ if (scanner.lowerEdge) {
+ // for x, this is the left edge.
+ // search for compatible top and bottom.
+
+//that means what? a value that is less than or equal the top and gte the bottom?
+//we can traverse the tree manually, looking for any in the range we want, but that means
+ //digging in and changing the bst to allow us to single step downwards, or some such.
+
+ //hmmm: POSTPONE. i want to do more things on the board, and this problem's gone WAY overtime.
+//hmmm: need to fix this implementation; it is bustard.
+
+
+ // we want to add the two y components of the rectangle to our tree.
+ bst.insert(new SortedElementKey(source.lr.y), new SortedElement(source.lr.y, true, source));
+ bst.insert(new SortedElementKey(source.ul.y), new SortedElement(source.ul.y, false, source));
+ } else {
+ // for x, this is the right edge.
+ // we will remove from the bst the two values for our top and bottom y.
+ bst.delete(new SortedElementKey(source.lr.y));
+ bst.delete(new SortedElementKey(source.ul.y));
+
+
+ }
+
+//what is missing?
+
+
+ }
+
+
+ return null;
+ }
+
+ public static void main(String[] argv)
+ {
+ Rectangle r1 = new Rectangle(new Point(0, 0), new Point(1, 1));
+ Rectangle r2 = new Rectangle(new Point(3, 2), new Point(4, 3));
+ Rectangle r3 = new Rectangle(new Point(2, 3), new Point(3, 4));
+ Rectangle r4 = new Rectangle(new Point(5, 6), new Point(7, 9));
+
+ Vector<Rectangle> list1 = new Vector<Rectangle>(Arrays.asList(r1, r2, r3));
+ Vector<Rectangle> list2 = new Vector<Rectangle>(Arrays.asList(r1, r2));
+ Vector<Rectangle> list3 = new Vector<Rectangle>(Arrays.asList(r1, r3, r4));
+
+ RectangleIntersector secto = new RectangleIntersector();
+
+ Vector<Rectangle> answer1 = secto.findOverlap(list1);
+ Vector<Rectangle> answer2 = secto.findOverlap(list2);
+ Vector<Rectangle> answer3 = secto.findOverlap(list3);
+
+ if (answer1 == null) {
+ System.out.println("FAILURE: test 1 did not find intersection in list");
+ } else {
+ System.out.println("OKAY: test 1 found intersections " + answer1.get(0) + " " + answer1.get(1));
+ }
+ if (answer2 != null) {
+ System.out.println("FAILURE: test 2 found an intersection in list that has none");
+ } else {
+ System.out.println("OKAY: test 2 no intersections found");
+ }
+ if (answer3 != null) {
+ System.out.println("FAILURE: test 3 found an intersection in list that has none");
+ } else {
+ System.out.println("OKAY: test 3 no intersections found");
+ }
+ }
+
+}