/* * Copyright (C) 2014 Alec Dhuse * * This program 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. * * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. */ package co.foldingmap.map.vector; import co.foldingmap.map.MapUtilities; import co.foldingmap.map.NumericValueOutOfRangeException; import co.foldingmap.xml.XmlOutput; /** * * @author Alec */ public class LatLonBox { protected float north, south, east, west; public LatLonBox() { north = 0; south = 0; east = 0; west = 0; } /** * Constructor for objects of class LatLonAltBox using floats. * * @param north North bounds of the box. * @param south South bounds of the box. * @param east East bounds of the box. * @param west West bounds of the box. */ public LatLonBox(float north, float south, float east, float west) { setNorth(north); setSouth(south); setEast(east); setWest(west); } /** * Returns if this LatLonBox contains a given Coordinate. * * @param c * @return */ public boolean contains(Coordinate c) { boolean returnValue = false; Coordinate max, min; float diff; try { max = new Coordinate(0, south, east); min = new Coordinate(0, north, west); if (west > 0 && east < 0) { diff = (180 - west) + Math.abs(180 + east); } else { diff = east - west; } if (c.isEastOf(min) && c.isWestOf(max, diff) && c.isNorthOf(max) && c.isSouthOf(min)) { returnValue = true; } } catch (Exception e) { System.err.println("Error in LatLonBox.contains(Coordinate) - " + e); } return returnValue; } /** * Returns if this LatLonBox equals another object. * * @param obj * @return */ @Override public boolean equals(Object obj) { if (obj instanceof LatLonBox) { LatLonBox box = (LatLonBox) obj; return (this.hashCode() == box.hashCode()); } else { return false; } } /** * Returns hash code for this object. * * @return */ @Override public int hashCode() { int hash = 7; hash = 53 * hash + Float.floatToIntBits(this.north); hash = 52 * hash + Float.floatToIntBits(this.south); hash = 51 * hash + Float.floatToIntBits(this.east); hash = 50 * hash + Float.floatToIntBits(this.west); return hash; } /** * Returns a Coordinate representing the center of this LatLonBox. * * @return */ public Coordinate getCenter() { Coordinate center; float centerLat, centerLon; try { centerLat = south + (getHeight() / 2.0f); centerLon = west + (getWidth() / 2.0f); center = new Coordinate(0, centerLat, centerLon); } catch (Exception e) { System.err.println("Error in LatLonBox.getCenter() - " + e); center = Coordinate.UNKNOWN_COORDINATE; } return center; } /** * Returns the height in Latitude degrees of this LatLonAltBox. * * @return */ public float getHeight() { float height = -1; if ((this.north > 0) && (this.south >= 0)) { height = north - south; } else if ((this.north > 0) && (this.south < 0)) { height = north + Math.abs(south); } else if ((this.north < 0) && (this.south < 0)) { height = Math.abs(south) - Math.abs(north); } return height; } /** * Returns this LatLonAltBox's North boundary Latitude. * @return */ public float getNorth() { return north; } /** * Returns this LatLonAltBox's South Latitude. * * @return */ public float getSouth() { return south; } /** * Returns this LatLonAltBox's East Longitude value. * * @return */ public float getEast() { return east; } /** * Returns this LatLonAltBox's West Longitude value. * @return */ public float getWest() { return west; } /** * Returns the width in Longitude Degrees of this LatLonAltBox. * * @return */ public float getWidth() { float width = -1; if ((this.west >= 0) && (this.east >= 0)) { width = east - west; } else if ((this.west < 0) && (this.east > 0)) { width = Math.abs(west) + east; } else if ((this.west > 0) && (this.east < 0)) { width = (180 - west) + (180 - Math.abs(east)); } else if ((this.west < 0) && (this.east < 0)) { width = Math.abs(east - west); } return width; } /** * Returns if this LatLonBox overlaps another LatLonAltBox. * @param box * @return */ public boolean overlaps(LatLonBox box) { boolean overlap = false; Coordinate northWest, northEast, southWest, southEast; Coordinate boxNorthWest, boxNorthEast, boxSouthWest, boxSouthEast; boolean northSouth = false; boolean eastWest = false; northWest = new Coordinate(0, north, west); northEast = new Coordinate(0, north, east); southWest = new Coordinate(0, south, west); southEast = new Coordinate(0, south, east); boxNorthWest = new Coordinate(0, box.getNorth(), box.getWest()); boxNorthEast = new Coordinate(0, box.getNorth(), box.getEast()); boxSouthWest = new Coordinate(0, box.getSouth(), box.getWest()); boxSouthEast = new Coordinate(0, box.getSouth(), box.getEast()); if (northWest.isSouthOf(boxNorthWest) && northWest.isNorthOf(boxSouthWest)) { northSouth = true; } else if (southWest.isSouthOf(boxNorthWest) && southWest.isNorthOf(boxSouthWest)) { northSouth = true; } else if (northWest.isNorthOf(boxNorthWest) && southWest.isSouthOf(boxSouthWest)) { northSouth = true; } else if (boxNorthWest.isNorthOf(northWest) && boxSouthWest.isSouthOf(southWest)) { northSouth = true; } if (northWest.isEastOf(boxNorthWest) && northWest.isWestOf(boxSouthEast, 90)) { eastWest = true; } else if (northWest.isWestOf(boxNorthWest, 90) && northWest.isEastOf(boxSouthWest)) { eastWest = true; } else if (southEast.isEastOf(boxNorthWest) && southEast.isWestOf(boxSouthEast, 90)) { eastWest = true; } else if (northWest.isWestOf(boxNorthWest, 90) && northEast.isEastOf(boxSouthEast)) { eastWest = true; } if (eastWest && northSouth) overlap = true; return overlap; } /** * Sets this LatLonAltBox's north value. * * @param north * A Latitude between -90 and 90 inclusive. * * @throws NumericValueOutOfRangeException */ public final void setNorth(float north) throws NumericValueOutOfRangeException { if ((north <= 90) && (north >= -90)) { this.north = north; } else { throw (new NumericValueOutOfRangeException(north)); } } /** * Sets this LatLonAltBox's south value. * * @param south * A Latitude between -90 and 90 inclusive. * @throws NumericValueOutOfRangeException */ public final void setSouth(float south) throws NumericValueOutOfRangeException { if ((south <= 90) && (south >= -90)) { this.south = south; } else { throw (new NumericValueOutOfRangeException(south)); } } /** * Sets this LatLonAltBox's east value. * * @param east * A Longitude between -180 and 180 inclusive. */ public final void setEast(float east){ this.east = (float) MapUtilities.normalizeLongitude(east); } /** * Sets this LatLonAltBox's west value. * * @param west * A Longitude between -180 and 180 inclusive. */ public final void setWest(float west) { this.west = (float) MapUtilities.normalizeLongitude(west); } /** * Returns a String Representation of this Object. * * @return */ @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append( "North: "); sb.append(Double.toString(north)); sb.append(" South: "); sb.append(Double.toString(south)); sb.append(" East: "); sb.append(Double.toString(east)); sb.append(" West: "); sb.append(Double.toString(west)); return sb.toString(); } /** * Writes the LatLonAltBox to fmXML. * * @param xmlWriter */ public void toXML(XmlOutput xmlWriter) { xmlWriter.openTag ("LatLonBox"); xmlWriter.writeTag("north", Double.toString(north)); xmlWriter.writeTag("south", Double.toString(south)); xmlWriter.writeTag("east", Double.toString(east)); xmlWriter.writeTag("west", Double.toString(west)); xmlWriter.closeTag("LatLonBox"); } }