| 1 | // License: GPL. For details, see LICENSE file. |
|---|
| 2 | package org.openstreetmap.josm.data.osm; |
|---|
| 3 | |
|---|
| 4 | import java.util.ArrayList; |
|---|
| 5 | import java.util.Arrays; |
|---|
| 6 | import java.util.List; |
|---|
| 7 | |
|---|
| 8 | import org.openstreetmap.josm.data.Bounds; |
|---|
| 9 | import org.openstreetmap.josm.data.coor.LatLon; |
|---|
| 10 | import org.openstreetmap.josm.tools.Utils; |
|---|
| 11 | |
|---|
| 12 | public class BBox { |
|---|
| 13 | |
|---|
| 14 | private double xmin = Double.POSITIVE_INFINITY; |
|---|
| 15 | private double xmax = Double.NEGATIVE_INFINITY; |
|---|
| 16 | private double ymin = Double.POSITIVE_INFINITY; |
|---|
| 17 | private double ymax = Double.NEGATIVE_INFINITY; |
|---|
| 18 | |
|---|
| 19 | public BBox(Bounds bounds) { |
|---|
| 20 | add(bounds.getMin()); |
|---|
| 21 | add(bounds.getMax()); |
|---|
| 22 | } |
|---|
| 23 | |
|---|
| 24 | public BBox(LatLon a, LatLon b) { |
|---|
| 25 | add(a); |
|---|
| 26 | add(b); |
|---|
| 27 | } |
|---|
| 28 | |
|---|
| 29 | public BBox(BBox copy) { |
|---|
| 30 | this.xmin = copy.xmin; |
|---|
| 31 | this.xmax = copy.xmax; |
|---|
| 32 | this.ymin = copy.ymin; |
|---|
| 33 | this.ymax = copy.ymax; |
|---|
| 34 | } |
|---|
| 35 | |
|---|
| 36 | public BBox(double a_x, double a_y, double b_x, double b_y) { |
|---|
| 37 | xmin = Math.min(a_x, b_x); |
|---|
| 38 | xmax = Math.max(a_x, b_x); |
|---|
| 39 | ymin = Math.min(a_y, b_y); |
|---|
| 40 | ymax = Math.max(a_y, b_y); |
|---|
| 41 | sanity(); |
|---|
| 42 | } |
|---|
| 43 | |
|---|
| 44 | public BBox(Way w) { |
|---|
| 45 | for (Node n : w.getNodes()) { |
|---|
| 46 | LatLon coor = n.getCoor(); |
|---|
| 47 | if (coor == null) { |
|---|
| 48 | continue; |
|---|
| 49 | } |
|---|
| 50 | add(coor); |
|---|
| 51 | } |
|---|
| 52 | } |
|---|
| 53 | |
|---|
| 54 | public BBox(Node n) { |
|---|
| 55 | LatLon coor = n.getCoor(); |
|---|
| 56 | if (coor == null) { |
|---|
| 57 | xmin = xmax = ymin = ymax = 0; |
|---|
| 58 | } else { |
|---|
| 59 | xmin = xmax = coor.lon(); |
|---|
| 60 | ymin = ymax = coor.lat(); |
|---|
| 61 | } |
|---|
| 62 | } |
|---|
| 63 | |
|---|
| 64 | private void sanity() { |
|---|
| 65 | if (xmin < -180.0) { |
|---|
| 66 | xmin = -180.0; |
|---|
| 67 | } |
|---|
| 68 | if (xmax > 180.0) { |
|---|
| 69 | xmax = 180.0; |
|---|
| 70 | } |
|---|
| 71 | if (ymin < -90.0) { |
|---|
| 72 | ymin = -90.0; |
|---|
| 73 | } |
|---|
| 74 | if (ymax > 90.0) { |
|---|
| 75 | ymax = 90.0; |
|---|
| 76 | } |
|---|
| 77 | } |
|---|
| 78 | |
|---|
| 79 | public void add(LatLon c) { |
|---|
| 80 | add(c.lon(), c.lat()); |
|---|
| 81 | } |
|---|
| 82 | |
|---|
| 83 | /** |
|---|
| 84 | * Extends this bbox to include the point (x, y) |
|---|
| 85 | */ |
|---|
| 86 | public void add(double x, double y) { |
|---|
| 87 | xmin = Math.min(xmin, x); |
|---|
| 88 | xmax = Math.max(xmax, x); |
|---|
| 89 | ymin = Math.min(ymin, y); |
|---|
| 90 | ymax = Math.max(ymax, y); |
|---|
| 91 | sanity(); |
|---|
| 92 | } |
|---|
| 93 | |
|---|
| 94 | public void add(BBox box) { |
|---|
| 95 | add(box.getTopLeft()); |
|---|
| 96 | add(box.getBottomRight()); |
|---|
| 97 | } |
|---|
| 98 | |
|---|
| 99 | 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 | } |
|---|