1 package org.feistymeow.algorithms;
3 import java.util.ArrayList;
4 import java.util.Arrays;
5 import java.util.Comparator;
6 import java.util.Vector;
9 * reports if any two rectangles in a list intersect. uses screen coordinates.
11 public class RectangleIntersector
13 public RectangleIntersector()
18 public static class Point
20 Point(double x, double y)
29 public static class Rectangle
31 Rectangle(Point ul, Point lr)
40 public static boolean doesPointOverlap(Point p, Rectangle r)
42 return p.x <= r.lr.x && p.x >= r.ul.x && p.y <= r.lr.y && p.y >= r.ul.y;
45 public static boolean doRectanglesOverlap(Rectangle r1, Rectangle r2)
47 return doesPointOverlap(r1.ul, r2) || doesPointOverlap(r1.lr, r2) || doesPointOverlap(r2.ul, r1) || doesPointOverlap(r2.lr, r1);
51 * find any overlapping pair of rectangles in the list provided.
53 public static Vector<Rectangle> findOverlapBruteForce(Vector<Rectangle> list)
55 // terrible brute force algorithm below.
56 for (int i = 0; i < list.size(); i++) {
57 for (int j = i; j < list.size(); j++) {
58 if (doRectanglesOverlap(list.get(i), list.get(j))) {
59 ArrayList<Rectangle> toReturn = new ArrayList<Rectangle>();
60 toReturn.add(list.get(i));
61 toReturn.add(list.get(j));
68 public static class SortedElement
70 double value; // the key.
71 boolean lowerEdge; // is this the left side?
72 Rectangle source; // where did this value come from.
74 public SortedElement(double value, boolean lowerEdge, Rectangle source)
77 this.lowerEdge = lowerEdge;
82 public static class SortedElementComparator implements Comparator<SortedElement>
85 public int compare(SortedElement k1, SortedElement k2)
87 SortedElementKey key1 = new SortedElementKey(k1.value);
88 return key1.compareTo(new SortedElementKey(k2.value));
94 public static class SortedElementKey implements Comparable<SortedElementKey>
96 public SortedElementKey(double key)
102 public int compareTo(SortedElementKey k2)
104 return (key == k2.key) ? 0 : (key < k2.key) ? -1 : 1;
111 * find any overlapping pair of rectangles in the list provided.
113 * this is classed as a good answer... if it works.
115 public static Vector<Rectangle> findOverlap(Vector<Rectangle> list)
117 // first phase, produce a sorted list of the x coordinates of the rectangles.
118 // this completes in O(n log(n)) time.
119 ArrayList<SortedElement> xEdges = new ArrayList<SortedElement>();
120 for (Rectangle r : list) {
121 xEdges.add(new SortedElement(r.lr.x, true, r));
122 xEdges.add(new SortedElement(r.ul.x, false, r));
124 // we're assuming this is an efficient sort; i've heard rumors that it's a heapsort.
125 // if so we're good. if not, we'd write our own heapsort (see feisty meow nucleus sorts.h).
126 xEdges.sort(new SortedElementComparator());
128 // second phase, crawl across the sorted list and build up a binary search tree
129 // with the y coordinates from the rectangles. we will use this to check for
131 BinarySearchTree<SortedElementKey, SortedElement> bst = new BinarySearchTree<SortedElementKey, SortedElement>();
133 for (SortedElement scanner : xEdges) {
134 Rectangle source = scanner.source;
135 if (scanner.lowerEdge) {
136 // for x, this is the left edge.
137 // search for compatible top and bottom.
139 //that means what? a value that is less than or equal the top and gte the bottom?
140 //we can traverse the tree manually, looking for any in the range we want, but that means
141 //digging in and changing the bst to allow us to single step downwards, or some such.
143 //hmmm: POSTPONE. i want to do more things on the board, and this problem's gone WAY overtime.
144 //hmmm: need to fix this implementation; it is bustard.
147 // we want to add the two y components of the rectangle to our tree.
148 bst.insert(new SortedElementKey(source.lr.y), new SortedElement(source.lr.y, true, source));
149 bst.insert(new SortedElementKey(source.ul.y), new SortedElement(source.ul.y, false, source));
151 // for x, this is the right edge.
152 // we will remove from the bst the two values for our top and bottom y.
153 bst.delete(new SortedElementKey(source.lr.y));
154 bst.delete(new SortedElementKey(source.ul.y));
168 public static void main(String[] argv)
170 Rectangle r1 = new Rectangle(new Point(0, 0), new Point(1, 1));
171 Rectangle r2 = new Rectangle(new Point(3, 2), new Point(4, 3));
172 Rectangle r3 = new Rectangle(new Point(2, 3), new Point(3, 4));
173 Rectangle r4 = new Rectangle(new Point(5, 6), new Point(7, 9));
175 Vector<Rectangle> list1 = new Vector<Rectangle>(Arrays.asList(r1, r2, r3));
176 Vector<Rectangle> list2 = new Vector<Rectangle>(Arrays.asList(r1, r2));
177 Vector<Rectangle> list3 = new Vector<Rectangle>(Arrays.asList(r1, r3, r4));
179 // RectangleIntersector secto = new RectangleIntersector();
181 Vector<Rectangle> answer1 = RectangleIntersector.findOverlap(list1);
182 Vector<Rectangle> answer2 = RectangleIntersector.findOverlap(list2);
183 Vector<Rectangle> answer3 = RectangleIntersector.findOverlap(list3);
185 if (answer1 == null) {
186 System.out.println("FAILURE: test 1 did not find intersection in list");
188 System.out.println("OKAY: test 1 found intersections " + answer1.get(0) + " " + answer1.get(1));
190 if (answer2 != null) {
191 System.out.println("FAILURE: test 2 found an intersection in list that has none");
193 System.out.println("OKAY: test 2 no intersections found");
195 if (answer3 != null) {
196 System.out.println("FAILURE: test 3 found an intersection in list that has none");
198 System.out.println("OKAY: test 3 no intersections found");