/******************************************************************************* * Copyright (c) 2015 - 2017 * <p> * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * <p> * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * <p> * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. *******************************************************************************/ package jsettlers.common.map.shapes; import jsettlers.common.position.ShortPoint2D; import jsettlers.common.utils.coordinates.CoordinateStream; import jsettlers.common.utils.coordinates.IBooleanCoordinateFunction; import java.util.Iterator; import java.util.NoSuchElementException; /** * This class defines an area on the map that is a rectangle on the screen. * * @author michael */ public final class MapRectangle implements IMapArea { private static final long serialVersionUID = -5451513891892255692L; private final short minX; private final short minY; final short width; final short height; public MapRectangle(short minx, short miny, short width, short height) { if (width < 0 || height < 0) { throw new IllegalArgumentException("Shape Size is negative"); } this.minX = minx; this.minY = miny; this.width = width; this.height = height; } public MapRectangle(int minx, int miny, int width, int height) { this((short) minx, (short) miny, (short) width, (short) height); } @Override public final boolean contains(ShortPoint2D position) { return contains(position.x, position.y); } public final boolean contains(int x, int y) { if (!containsLine(y)) { return false; } if (x < getLineStartX(y - getMinY()) || x > getLineEndX(y - getMinY())) { return false; } return true; } public final boolean containsLine(int y) { return y >= getMinY() && y < getMinY() + height; } @Override public final Iterator<ShortPoint2D> iterator() { return new RectangleIterator(); } private final static int getOffsetForLine(int line) { return line / 2; } /** * Gets the first x coordinate contained by a line. * * @param line * The line relative to the first line of this rectangle. */ public final int getLineStartX(int line) { return minX + getOffsetForLine(line); } /** * Gets the last x coordinate contained by a line. * * @param line * The line relative to the first line of this rectangle. */ public final int getLineEndX(int line) { return getLineStartX(line) + this.width - 1; } public final int getLineY(int line) { return minY + line; } public final short getLines() { return height; } public final short getLineLength() { return width; } public short getMinX() { return minX; } public short getMinY() { return minY; } public final short getWidth() { return width; } public final short getHeight() { return height; } @Override public CoordinateStream stream() { return new CoordinateStream() { @Override public boolean iterate(IBooleanCoordinateFunction function) { for (int relativeY = 0; relativeY < height; relativeY++) { int lineStartX = getLineStartX(relativeY); for (int relativeX = 0; relativeX < width; relativeX++) { int x = lineStartX + relativeX; int y = getLineY(relativeY); if (!function.apply(x, y)) { return false; } } } return true; } }; } private class RectangleIterator implements Iterator<ShortPoint2D> { private int relativeX = 0; private int relativeY = 0; @Override public boolean hasNext() { return relativeY < height && width > 0; } @Override public ShortPoint2D next() { if (relativeY < height && width > 0) { int x = getLineStartX(relativeY) + relativeX; int y = getLineY(relativeY); ShortPoint2D pos = new ShortPoint2D(x, y); relativeX++; if (relativeX >= width) { relativeX = 0; relativeY++; } return pos; } else { throw new NoSuchElementException("There are no more elements in the shape"); } } @Override public void remove() { throw new UnsupportedOperationException("Cannot remove tiles from a Shape"); } } }