package org.terasology.math; import java.util.ArrayList; import java.util.List; /** * 2D Rectangle */ public class Rect2i { // position public int x; public int y; // size public int w; public int h; public Rect2i(int x, int y, int w, int h) { this.x = x; this.y = y; this.w = w; this.h = h; } // a - b // @pre a and b have the same size // @return list of disjunct rects building the subtraction result (eg. L-shape) public static List<Rect2i> subtractEqualsSized(Rect2i a, Rect2i b) { ArrayList<Rect2i> result = new ArrayList<Rect2i>(); boolean overlap = a.overlaps(b); boolean equal = (a.x == b.x) && (a.y == b.y); if (equal) { // empty list return result; } if (!overlap) { // a does not change result.add(a); return result; } // invariant: equal size and overlapping and not equal position int splitCenterX = (a.x < b.x) ? b.minX() : b.maxX(); int splitCenterY = (a.y < b.y) ? b.minY() : b.maxY(); subtractEqualsSizedHelper(a.minX(), a.minY(), b, splitCenterX, splitCenterY, result); subtractEqualsSizedHelper(a.maxX(), a.minY(), b, splitCenterX, splitCenterY, result); subtractEqualsSizedHelper(a.minX(), a.maxY(), b, splitCenterX, splitCenterY, result); subtractEqualsSizedHelper(a.maxX(), a.maxY(), b, splitCenterX, splitCenterY, result); return result; } public String toString() { return String.format("x=%d y=%d w=%d h=%d", x, y, w, h); } private static void subtractEqualsSizedHelper(int x, int y, Rect2i b, int splitCenterX, int splitCenterY, ArrayList<Rect2i> result) { if (!b.contains(x, y) && x != splitCenterX && y != splitCenterY) { Rect2i candidate = createRectSpanning2Points(x, y, splitCenterX, splitCenterY); if (candidate.w * candidate.h > 0) { result.add(candidate); } } } // @return minimum rect that contains both points public static Rect2i createRectSpanning2Points(int x0, int y0, int x1, int y1) { int x = Math.min(x0, x1); int y = Math.min(y0, y1); int w = Math.max(x0 - x, x1 - x); int h = Math.max(y0 - y, y1 - y); return new Rect2i(x, y, w, h); } /** * Returns true if the Rect contains the given point. * * @param x The x part of point to check for inclusion * @param y The y part of point to check for inclusion * @return True if containing */ public boolean contains(int x, int y) { return !(maxX() < x || minX() > x) && !(maxY() < y || minY() > y); } /** * Returns true if this Rect overlaps the given Rect. * * @param b The Rect to check for overlapping * @return True if overlapping */ public boolean overlaps(Rect2i b) { return !(maxX() < b.minX() || minX() > b.maxX()) && !(maxY() < b.minY() || minY() > b.maxY()); } public int maxX() { return x + w; } public int minX() { return x; } public int maxY() { return y + h; } public int minY() { return y; } public int area() { return w * h; } }