package org.expeditee.core.bounds; import java.util.LinkedList; import java.util.List; import org.expeditee.core.Point; /** * The CombinationBounds class represents a collection of bounds, which * may be disjoint. A point is considered inside the CombinationBounds if * it is inside any of the individual bounds in the collection (i.e. if it * is inside the conjunction of the individual bounds). If the combination * bounds has no component bounds, then no points are inside it. * * @author cts16 */ public class CombinationBounds extends Bounds { /** The collection of bounds. */ protected List _bounds; /** Default constructor. */ public CombinationBounds() { this(null); } /** Standard constructor. */ public CombinationBounds(Bounds b) { _bounds = new LinkedList(); add(b); } /** Copy constructor. */ public CombinationBounds(CombinationBounds other) { _bounds = new LinkedList(); for (Bounds b : other._bounds) add(b); } /** Adds a bounds to the combination. */ public CombinationBounds add(Bounds b) { // Only valid Bounds are allowed in the collection if (b == null) return this; _bounds.add(b); return this; } /** Gets the bounds at the given index in this combination. */ public Bounds get(int index) { if (0 <= index && index < _bounds.size()) return _bounds.get(index); return null; } /** Removes all component bounds. */ public CombinationBounds clear() { _bounds.clear(); return this; } /** Whether this combination bounds has no component bounds. */ public boolean isEmpty() { return _bounds.isEmpty(); } @Override public boolean contains(int x, int y) { // If any component bounds contains the point, then the combination as // a whole does as well for (Bounds b : _bounds) { if (b.contains(x, y)) return true; } // No component contained the point return false; } @Override public int getMaxX() { // +1 makes it safe to do math.abs on int maxX = Integer.MIN_VALUE + 1; for (Bounds b : _bounds) { int thisX = b.getMaxX(); if (thisX > maxX) maxX = thisX; } return maxX; } @Override public int getMinX() { int minX = Integer.MAX_VALUE; for (Bounds b : _bounds) { int thisX = b.getMinX(); if (thisX < minX) minX = thisX; } return minX; } @Override public int getMaxY() { // +1 makes it safe to do math.abs on int maxY = Integer.MIN_VALUE + 1; for (Bounds b : _bounds) { int thisY = b.getMaxY(); if (thisY > maxY) maxY = thisY; } return maxY; } @Override public int getMinY() { int minY = Integer.MAX_VALUE; for (Bounds b : _bounds) { int thisY = b.getMinY(); if (thisY < minY) minY = thisY; } return minY; } @Override public CombinationBounds translate(int x, int y) { for (Bounds b : _bounds) { b.translate(x, y); } return this; } @Override public boolean equals(Bounds other) { if (other instanceof CombinationBounds) { CombinationBounds c = (CombinationBounds) other; if (_bounds.size() == c._bounds.size()) { for (int i = 0; i < _bounds.size(); i++) { if (!(_bounds.get(i).equals(c._bounds.get(i)))) return false; } return true; } } return false; } @Override public boolean intersects(Bounds other) { for (Bounds b : _bounds) { if (b.intersects(other)) return true; } return false; } @Override public boolean intersects(AxisAlignedBoxBounds other) { return intersects((Bounds) other); } @Override public boolean intersects(CombinationBounds other) { return intersects((Bounds) other); } @Override public boolean intersects(EllipticalBounds other) { return intersects((Bounds) other); } @Override public boolean intersects(PolygonBounds other) { return intersects((Bounds) other); } @Override public double getArea() { // TODO Complete. Difficult as have to take into account overlapping areas. cts16 System.err.println("Unimplemented method: CombinationBounds.getArea()"); return 0; } @Override public boolean perimeterContains(Point p, double error) { for (Bounds b : _bounds) { if (b.perimeterContains(p, error)) { for (Bounds b2 : _bounds) { if (b2 != b && b2.contains(p) && !b2.perimeterContains(p, error)) return false; } return true; } } return false; } @Override public boolean completelyContains(AxisAlignedBoxBounds other) { // TODO Complete. Difficult as we have to take into account conjoined areas. cts16 System.err.println("Unimplemented method: CombinationBounds.completelyContains(AxisAlignedBoxBounds)"); return false; } @Override public boolean completelyContains(CombinationBounds other) { // TODO Complete. Difficult as we have to take into account conjoined areas. cts16 System.err.println("Unimplemented method: CombinationBounds.completelyContains(CombinationBounds)"); return false; } @Override public boolean completelyContains(EllipticalBounds other) { // TODO Complete. Difficult as we have to take into account conjoined areas. cts16 System.err.println("Unimplemented method: CombinationBounds.completelyContains(EllipticalBounds)"); return false; } @Override public boolean completelyContains(PolygonBounds other) { // TODO Complete. Difficult as we have to take into account conjoined areas. cts16 System.err.println("Unimplemented method: CombinationBounds.completelyContains(PolygonBounds)"); return false; } @Override public CombinationBounds clone() { return new CombinationBounds(this); } }