/******************************************************************************* * This file is part of logisim-evolution. * * logisim-evolution is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * logisim-evolution is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with logisim-evolution. If not, see <http://www.gnu.org/licenses/>. * * Original code by Carl Burch (http://www.cburch.com), 2011. * Subsequent modifications by : * + Haute École Spécialisée Bernoise * http://www.bfh.ch * + Haute École du paysage, d'ingénierie et d'architecture de Genève * http://hepia.hesge.ch/ * + Haute École d'Ingénierie et de Gestion du Canton de Vaud * http://www.heig-vd.ch/ * The project is currently maintained by : * + REDS Institute - HEIG-VD * Yverdon-les-Bains, Switzerland * http://reds.heig-vd.ch *******************************************************************************/ package com.cburch.logisim.data; import com.cburch.logisim.util.Cache; /** * Represents an immutable rectangular bounding box. This is analogous to * java.awt's <code>Point</code> class, except that objects of this type are * immutable. */ public class Location implements Comparable<Location> { public static Location create(int x, int y) { int hashCode = 31 * x + y; Object ret = cache.get(hashCode); if (ret != null) { Location loc = (Location) ret; if (loc.x == x && loc.y == y) return loc; } Location loc = new Location(hashCode, x, y); cache.put(hashCode, loc); return loc; } public static Location parse(String value) { String base = value; value = value.trim(); if (value.charAt(0) == '(') { int len = value.length(); if (value.charAt(len - 1) != ')') { throw new NumberFormatException("invalid point '" + base + "'"); } value = value.substring(1, len - 1); } value = value.trim(); int comma = value.indexOf(','); if (comma < 0) { comma = value.indexOf(' '); if (comma < 0) { throw new NumberFormatException("invalid point '" + base + "'"); } } int x = Integer.parseInt(value.substring(0, comma).trim()); int y = Integer.parseInt(value.substring(comma + 1).trim()); return Location.create(x, y); } private static final Cache cache = new Cache(); private final int hashCode; private final int x; private final int y; private Location(int hashCode, int x, int y) { this.hashCode = hashCode; this.x = x; this.y = y; } public int compareTo(Location other) { if (this.x != other.x) return this.x - other.x; else return this.y - other.y; } @Override public boolean equals(Object other_obj) { if (!(other_obj instanceof Location)) return false; Location other = (Location) other_obj; return this.x == other.x && this.y == other.y; } public int getX() { return x; } public int getY() { return y; } @Override public int hashCode() { return hashCode; } public int manhattanDistanceTo(int x, int y) { return Math.abs(x - this.x) + Math.abs(y - this.y); } public int manhattanDistanceTo(Location o) { return Math.abs(o.x - this.x) + Math.abs(o.y - this.y); } // rotates this around (xc,yc) assuming that this is facing in the // from direction and the returned bounds should face in the to direction. public Location rotate(Direction from, Direction to, int xc, int yc) { int degrees = to.toDegrees() - from.toDegrees(); while (degrees >= 360) degrees -= 360; while (degrees < 0) degrees += 360; int dx = x - xc; int dy = y - yc; if (degrees == 90) { return create(xc + dy, yc - dx); } else if (degrees == 180) { return create(xc - dx, yc - dy); } else if (degrees == 270) { return create(xc - dy, yc + dx); } else { return this; } } @Override public String toString() { return "(" + x + "," + y + ")"; } public Location translate(Direction dir, int dist) { return translate(dir, dist, 0); } public Location translate(Direction dir, int dist, int right) { if (dist == 0 && right == 0) return this; if (dir == Direction.EAST) return Location.create(x + dist, y + right); if (dir == Direction.WEST) return Location.create(x - dist, y - right); if (dir == Direction.SOUTH) return Location.create(x - right, y + dist); if (dir == Direction.NORTH) return Location.create(x + right, y - dist); return Location.create(x + dist, y + right); } public Location translate(int dx, int dy) { if (dx == 0 && dy == 0) return this; return Location.create(x + dx, y + dy); } }