001 // License: GPL. For details, see LICENSE file. 002 package org.openstreetmap.josm.data.osm; 003 004 import java.util.ArrayList; 005 import java.util.Arrays; 006 import java.util.List; 007 008 import org.openstreetmap.josm.data.Bounds; 009 import org.openstreetmap.josm.data.coor.LatLon; 010 import org.openstreetmap.josm.tools.Utils; 011 012 public class BBox { 013 014 private double xmin = Double.POSITIVE_INFINITY; 015 private double xmax = Double.NEGATIVE_INFINITY; 016 private double ymin = Double.POSITIVE_INFINITY; 017 private double ymax = Double.NEGATIVE_INFINITY; 018 019 public BBox(Bounds bounds) { 020 add(bounds.getMin()); 021 add(bounds.getMax()); 022 } 023 024 public BBox(LatLon a, LatLon b) { 025 add(a); 026 add(b); 027 } 028 029 public BBox(BBox copy) { 030 this.xmin = copy.xmin; 031 this.xmax = copy.xmax; 032 this.ymin = copy.ymin; 033 this.ymax = copy.ymax; 034 } 035 036 public BBox(double a_x, double a_y, double b_x, double b_y) { 037 xmin = Math.min(a_x, b_x); 038 xmax = Math.max(a_x, b_x); 039 ymin = Math.min(a_y, b_y); 040 ymax = Math.max(a_y, b_y); 041 sanity(); 042 } 043 044 public BBox(Way w) { 045 for (Node n : w.getNodes()) { 046 LatLon coor = n.getCoor(); 047 if (coor == null) { 048 continue; 049 } 050 add(coor); 051 } 052 } 053 054 public BBox(Node n) { 055 LatLon coor = n.getCoor(); 056 if (coor == null) { 057 xmin = xmax = ymin = ymax = 0; 058 } else { 059 xmin = xmax = coor.lon(); 060 ymin = ymax = coor.lat(); 061 } 062 } 063 064 private void sanity() { 065 if (xmin < -180.0) { 066 xmin = -180.0; 067 } 068 if (xmax > 180.0) { 069 xmax = 180.0; 070 } 071 if (ymin < -90.0) { 072 ymin = -90.0; 073 } 074 if (ymax > 90.0) { 075 ymax = 90.0; 076 } 077 } 078 079 public void add(LatLon c) { 080 add(c.lon(), c.lat()); 081 } 082 083 /** 084 * Extends this bbox to include the point (x, y) 085 */ 086 public void add(double x, double y) { 087 xmin = Math.min(xmin, x); 088 xmax = Math.max(xmax, x); 089 ymin = Math.min(ymin, y); 090 ymax = Math.max(ymax, y); 091 sanity(); 092 } 093 094 public void add(BBox box) { 095 add(box.getTopLeft()); 096 add(box.getBottomRight()); 097 } 098 099 public void addPrimitive(OsmPrimitive primitive, double extraSpace) { 100 BBox primBbox = primitive.getBBox(); 101 add(primBbox.xmin - extraSpace, primBbox.ymin - extraSpace); 102 add(primBbox.xmax + extraSpace, primBbox.ymax + extraSpace); 103 } 104 105 public double height() { 106 return ymax-ymin; 107 } 108 109 public double width() { 110 return xmax-xmin; 111 } 112 113 /** 114 * Tests, weather the bbox b lies completely inside 115 * this bbox. 116 */ 117 public boolean bounds(BBox b) { 118 if (!(xmin <= b.xmin) || 119 !(xmax >= b.xmax) || 120 !(ymin <= b.ymin) || 121 !(ymax >= b.ymax)) 122 return false; 123 return true; 124 } 125 126 /** 127 * Tests, weather the Point c lies within the bbox. 128 */ 129 public boolean bounds(LatLon c) { 130 if ((xmin <= c.lon()) && 131 (xmax >= c.lon()) && 132 (ymin <= c.lat()) && 133 (ymax >= c.lat())) 134 return true; 135 return false; 136 } 137 138 /** 139 * Tests, weather two BBoxes intersect as an area. 140 * I.e. whether there exists a point that lies in both of them. 141 */ 142 public boolean intersects(BBox b) { 143 if (xmin > b.xmax) 144 return false; 145 if (xmax < b.xmin) 146 return false; 147 if (ymin > b.ymax) 148 return false; 149 if (ymax < b.ymin) 150 return false; 151 return true; 152 } 153 154 /** 155 * Returns a list of all 4 corners of the bbox rectangle. 156 */ 157 public List<LatLon> points() { 158 LatLon p1 = new LatLon(ymin, xmin); 159 LatLon p2 = new LatLon(ymin, xmax); 160 LatLon p3 = new LatLon(ymax, xmin); 161 LatLon p4 = new LatLon(ymax, xmax); 162 List<LatLon> ret = new ArrayList<LatLon>(4); 163 ret.add(p1); 164 ret.add(p2); 165 ret.add(p3); 166 ret.add(p4); 167 return ret; 168 } 169 170 public LatLon getTopLeft() { 171 return new LatLon(ymax, xmin); 172 } 173 174 public LatLon getBottomRight() { 175 return new LatLon(ymin, xmax); 176 } 177 178 public LatLon getCenter() { 179 return new LatLon(ymin + (ymax-ymin)/2.0, xmin + (xmax-xmin)/2.0); 180 } 181 182 @Override 183 public int hashCode() { 184 return (int)(ymin * xmin); 185 } 186 187 @Override 188 public boolean equals(Object o) { 189 if (o instanceof BBox) { 190 BBox b = (BBox)o; 191 return b.xmax == xmax && b.ymax == ymax && b.xmin == xmin && b.ymin == ymin; 192 } else 193 return false; 194 } 195 196 @Override 197 public String toString() { 198 return "[ x: " + xmin + " -> " + xmax + 199 ", y: " + ymin + " -> " + ymax + " ]"; 200 } 201 202 public String toStringCSV(String separator) { 203 return Utils.join(separator, Arrays.asList( 204 LatLon.cDdFormatter.format(xmin), 205 LatLon.cDdFormatter.format(ymin), 206 LatLon.cDdFormatter.format(xmax), 207 LatLon.cDdFormatter.format(ymax))); 208 } 209 }