source: josm/trunk/src/org/openstreetmap/josm/data/Bounds.java@ 12395

Last change on this file since 12395 was 12374, checked in by michael2402, 7 years ago

Javadoc for the data package.

  • Property svn:eol-style set to native
File size: 20.9 KB
RevLine 
[6380]1// License: GPL. For details, see LICENSE file.
[71]2package org.openstreetmap.josm.data;
3
[2456]4import static org.openstreetmap.josm.tools.I18n.tr;
5
[746]6import java.awt.geom.Rectangle2D;
[2717]7import java.text.DecimalFormat;
[2845]8import java.text.MessageFormat;
[9371]9import java.util.Objects;
[10806]10import java.util.function.Consumer;
[746]11
[12161]12import org.openstreetmap.josm.data.coor.ILatLon;
[71]13import org.openstreetmap.josm.data.coor.LatLon;
[6203]14import org.openstreetmap.josm.data.osm.BBox;
[10806]15import org.openstreetmap.josm.data.projection.Projection;
[2845]16import org.openstreetmap.josm.tools.CheckParameterUtil;
[71]17
18/**
[1169]19 * This is a simple data class for "rectangular" areas of the world, given in
[2943]20 * lat/lon min/max values. The values are rounded to LatLon.OSM_SERVER_PRECISION
[1169]21 *
[12171]22 * @author imi
23 *
[12161]24 * @see BBox to represent invalid areas.
[71]25 */
26public class Bounds {
[1169]27 /**
28 * The minimum and maximum coordinates.
29 */
[2805]30 private double minLat, minLon, maxLat, maxLon;
[2456]31
[11272]32 /**
33 * Gets the point that has both the minimal lat and lon coordinate
34 * @return The point
35 */
[2327]36 public LatLon getMin() {
[2805]37 return new LatLon(minLat, minLon);
[2327]38 }
[71]39
[6203]40 /**
41 * Returns min latitude of bounds. Efficient shortcut for {@code getMin().lat()}.
[6830]42 *
[6203]43 * @return min latitude of bounds.
44 * @since 6203
45 */
46 public double getMinLat() {
47 return minLat;
48 }
49
50 /**
51 * Returns min longitude of bounds. Efficient shortcut for {@code getMin().lon()}.
[6830]52 *
[6203]53 * @return min longitude of bounds.
54 * @since 6203
55 */
56 public double getMinLon() {
57 return minLon;
58 }
59
[11272]60 /**
61 * Gets the point that has both the maximum lat and lon coordinate
62 * @return The point
63 */
[2327]64 public LatLon getMax() {
[2805]65 return new LatLon(maxLat, maxLon);
[2327]66 }
[6069]67
[6203]68 /**
69 * Returns max latitude of bounds. Efficient shortcut for {@code getMax().lat()}.
[6830]70 *
[6203]71 * @return max latitude of bounds.
72 * @since 6203
73 */
74 public double getMaxLat() {
75 return maxLat;
76 }
77
78 /**
79 * Returns max longitude of bounds. Efficient shortcut for {@code getMax().lon()}.
[6830]80 *
[6203]81 * @return max longitude of bounds.
82 * @since 6203
83 */
84 public double getMaxLon() {
85 return maxLon;
86 }
87
[12374]88 /**
89 * The method used by the {@link Bounds#Bounds(String, String, ParseMethod)} constructor
90 */
[4521]91 public enum ParseMethod {
[12374]92 /**
93 * Order: minlat, minlon, maxlat, maxlon
94 */
[4521]95 MINLAT_MINLON_MAXLAT_MAXLON,
[12374]96 /**
97 * Order: left, bottom, right, top
98 */
[4521]99 LEFT_BOTTOM_RIGHT_TOP
100 }
[6069]101
[1169]102 /**
[6203]103 * Construct bounds out of two points. Coords will be rounded.
[9243]104 * @param min min lat/lon
105 * @param max max lat/lon
[1169]106 */
107 public Bounds(LatLon min, LatLon max) {
[2805]108 this(min.lat(), min.lon(), max.lat(), max.lon());
[1169]109 }
[71]110
[10910]111 /**
112 * Constructs bounds out of two points.
113 * @param min min lat/lon
114 * @param max max lat/lon
115 * @param roundToOsmPrecision defines if lat/lon will be rounded
116 */
[5235]117 public Bounds(LatLon min, LatLon max, boolean roundToOsmPrecision) {
118 this(min.lat(), min.lon(), max.lat(), max.lon(), roundToOsmPrecision);
119 }
120
[9243]121 /**
[10910]122 * Constructs bounds out a single point. Coords will be rounded.
[9243]123 * @param b lat/lon
124 */
[1724]125 public Bounds(LatLon b) {
[5235]126 this(b, true);
127 }
[6069]128
[6203]129 /**
130 * Single point Bounds defined by lat/lon {@code b}.
131 * Coordinates will be rounded to osm precision if {@code roundToOsmPrecision} is true.
[6830]132 *
[6203]133 * @param b lat/lon of given point.
134 * @param roundToOsmPrecision defines if lat/lon will be rounded.
135 */
[5235]136 public Bounds(LatLon b, boolean roundToOsmPrecision) {
[6203]137 this(b.lat(), b.lon(), roundToOsmPrecision);
138 }
[6830]139
[6203]140 /**
141 * Single point Bounds defined by point [lat,lon].
142 * Coordinates will be rounded to osm precision if {@code roundToOsmPrecision} is true.
[6830]143 *
[6203]144 * @param lat latitude of given point.
145 * @param lon longitude of given point.
146 * @param roundToOsmPrecision defines if lat/lon will be rounded.
147 * @since 6203
148 */
149 public Bounds(double lat, double lon, boolean roundToOsmPrecision) {
[4573]150 // Do not call this(b, b) to avoid GPX performance issue (see #7028) until roundToOsmPrecision() is improved
[5235]151 if (roundToOsmPrecision) {
[6203]152 this.minLat = LatLon.roundToOsmPrecision(lat);
153 this.minLon = LatLon.roundToOsmPrecision(lon);
[5235]154 } else {
[6203]155 this.minLat = lat;
156 this.minLon = lon;
[5235]157 }
[4573]158 this.maxLat = this.minLat;
159 this.maxLon = this.minLon;
[1724]160 }
[2456]161
[10910]162 /**
163 * Constructs bounds out of two points. Coords will be rounded.
164 * @param minlat min lat
165 * @param minlon min lon
166 * @param maxlat max lat
167 * @param maxlon max lon
168 */
[2327]169 public Bounds(double minlat, double minlon, double maxlat, double maxlon) {
[5235]170 this(minlat, minlon, maxlat, maxlon, true);
[2327]171 }
[2456]172
[10910]173 /**
174 * Constructs bounds out of two points.
175 * @param minlat min lat
176 * @param minlon min lon
177 * @param maxlat max lat
178 * @param maxlon max lon
179 * @param roundToOsmPrecision defines if lat/lon will be rounded
180 */
[5235]181 public Bounds(double minlat, double minlon, double maxlat, double maxlon, boolean roundToOsmPrecision) {
182 if (roundToOsmPrecision) {
183 this.minLat = LatLon.roundToOsmPrecision(minlat);
184 this.minLon = LatLon.roundToOsmPrecision(minlon);
185 this.maxLat = LatLon.roundToOsmPrecision(maxlat);
186 this.maxLon = LatLon.roundToOsmPrecision(maxlon);
187 } else {
188 this.minLat = minlat;
189 this.minLon = minlon;
190 this.maxLat = maxlat;
191 this.maxLon = maxlon;
192 }
193 }
194
[10910]195 /**
196 * Constructs bounds out of two points. Coords will be rounded.
197 * @param coords exactly 4 values: min lat, min lon, max lat, max lon
198 * @throws IllegalArgumentException if coords does not contain 4 double values
199 */
[11747]200 public Bounds(double... coords) {
[5235]201 this(coords, true);
202 }
203
[10910]204 /**
205 * Constructs bounds out of two points.
206 * @param coords exactly 4 values: min lat, min lon, max lat, max lon
207 * @param roundToOsmPrecision defines if lat/lon will be rounded
208 * @throws IllegalArgumentException if coords does not contain 4 double values
209 */
[8443]210 public Bounds(double[] coords, boolean roundToOsmPrecision) {
[2845]211 CheckParameterUtil.ensureParameterNotNull(coords, "coords");
[2327]212 if (coords.length != 4)
[2845]213 throw new IllegalArgumentException(MessageFormat.format("Expected array of length 4, got {0}", coords.length));
[5235]214 if (roundToOsmPrecision) {
215 this.minLat = LatLon.roundToOsmPrecision(coords[0]);
216 this.minLon = LatLon.roundToOsmPrecision(coords[1]);
217 this.maxLat = LatLon.roundToOsmPrecision(coords[2]);
218 this.maxLon = LatLon.roundToOsmPrecision(coords[3]);
219 } else {
220 this.minLat = coords[0];
221 this.minLon = coords[1];
222 this.maxLat = coords[2];
223 this.maxLon = coords[3];
224 }
[2327]225 }
[2456]226
[12374]227 /**
228 * Parse the bounds in order {@link ParseMethod#MINLAT_MINLON_MAXLAT_MAXLON}
229 * @param asString The string
230 * @param separator The separation regex
231 */
[8291]232 public Bounds(String asString, String separator) {
[4521]233 this(asString, separator, ParseMethod.MINLAT_MINLON_MAXLAT_MAXLON);
234 }
235
[12374]236 /**
237 * Parse the bounds from a given string and round to OSM precision
238 * @param asString The string
239 * @param separator The separation regex
240 * @param parseMethod The order of the numbers
241 */
[8291]242 public Bounds(String asString, String separator, ParseMethod parseMethod) {
[5235]243 this(asString, separator, parseMethod, true);
244 }
245
[12374]246 /**
247 * Parse the bounds from a given string
248 * @param asString The string
249 * @param separator The separation regex
250 * @param parseMethod The order of the numbers
251 * @param roundToOsmPrecision Whether to round to OSM precision
252 */
[8291]253 public Bounds(String asString, String separator, ParseMethod parseMethod, boolean roundToOsmPrecision) {
[2845]254 CheckParameterUtil.ensureParameterNotNull(asString, "asString");
[2327]255 String[] components = asString.split(separator);
[2456]256 if (components.length != 4)
[8509]257 throw new IllegalArgumentException(
258 MessageFormat.format("Exactly four doubles expected in string, got {0}: {1}", components.length, asString));
[2327]259 double[] values = new double[4];
[8510]260 for (int i = 0; i < 4; i++) {
[2327]261 try {
262 values[i] = Double.parseDouble(components[i]);
[8510]263 } catch (NumberFormatException e) {
[6798]264 throw new IllegalArgumentException(MessageFormat.format("Illegal double value ''{0}''", components[i]), e);
[2327]265 }
266 }
[6069]267
[4521]268 switch (parseMethod) {
269 case LEFT_BOTTOM_RIGHT_TOP:
[5235]270 this.minLat = initLat(values[1], roundToOsmPrecision);
271 this.minLon = initLon(values[0], roundToOsmPrecision);
272 this.maxLat = initLat(values[3], roundToOsmPrecision);
273 this.maxLon = initLon(values[2], roundToOsmPrecision);
[4521]274 break;
275 case MINLAT_MINLON_MAXLAT_MAXLON:
276 default:
[5235]277 this.minLat = initLat(values[0], roundToOsmPrecision);
278 this.minLon = initLon(values[1], roundToOsmPrecision);
279 this.maxLat = initLat(values[2], roundToOsmPrecision);
280 this.maxLon = initLon(values[3], roundToOsmPrecision);
[4521]281 }
[4522]282 }
[6069]283
[5235]284 protected static double initLat(double value, boolean roundToOsmPrecision) {
[4522]285 if (!LatLon.isValidLat(value))
286 throw new IllegalArgumentException(tr("Illegal latitude value ''{0}''", value));
[5235]287 return roundToOsmPrecision ? LatLon.roundToOsmPrecision(value) : value;
[4522]288 }
[2686]289
[5235]290 protected static double initLon(double value, boolean roundToOsmPrecision) {
[4522]291 if (!LatLon.isValidLon(value))
292 throw new IllegalArgumentException(tr("Illegal longitude value ''{0}''", value));
[5235]293 return roundToOsmPrecision ? LatLon.roundToOsmPrecision(value) : value;
[2327]294 }
[2456]295
[6203]296 /**
297 * Creates new {@code Bounds} from an existing one.
298 * @param other The bounds to copy
299 */
300 public Bounds(final Bounds other) {
301 this(other.minLat, other.minLon, other.maxLat, other.maxLon);
[2327]302 }
[1724]303
[10910]304 /**
305 * Creates new {@code Bounds} from a rectangle.
306 * @param rect The rectangle
307 */
[2327]308 public Bounds(Rectangle2D rect) {
[2805]309 this(rect.getMinY(), rect.getMinX(), rect.getMaxY(), rect.getMaxX());
[2327]310 }
[2456]311
312 /**
313 * Creates new bounds around a coordinate pair <code>center</code>. The
314 * new bounds shall have an extension in latitude direction of <code>latExtent</code>,
315 * and in longitude direction of <code>lonExtent</code>.
[2512]316 *
[2456]317 * @param center the center coordinate pair. Must not be null.
[6830]318 * @param latExtent the latitude extent. &gt; 0 required.
319 * @param lonExtent the longitude extent. &gt; 0 required.
[8291]320 * @throws IllegalArgumentException if center is null
321 * @throws IllegalArgumentException if latExtent &lt;= 0
322 * @throws IllegalArgumentException if lonExtent &lt;= 0
[2456]323 */
324 public Bounds(LatLon center, double latExtent, double lonExtent) {
[2845]325 CheckParameterUtil.ensureParameterNotNull(center, "center");
[2456]326 if (latExtent <= 0.0)
[6830]327 throw new IllegalArgumentException(MessageFormat.format("Parameter ''{0}'' > 0.0 expected, got {1}", "latExtent", latExtent));
[2456]328 if (lonExtent <= 0.0)
[6830]329 throw new IllegalArgumentException(MessageFormat.format("Parameter ''{0}'' > 0.0 expected, got {1}", "lonExtent", lonExtent));
[2456]330
[4580]331 this.minLat = LatLon.roundToOsmPrecision(LatLon.toIntervalLat(center.lat() - latExtent / 2));
332 this.minLon = LatLon.roundToOsmPrecision(LatLon.toIntervalLon(center.lon() - lonExtent / 2));
333 this.maxLat = LatLon.roundToOsmPrecision(LatLon.toIntervalLat(center.lat() + latExtent / 2));
334 this.maxLon = LatLon.roundToOsmPrecision(LatLon.toIntervalLon(center.lon() + lonExtent / 2));
[2456]335 }
336
[6203]337 /**
338 * Creates BBox with same coordinates.
[6830]339 *
[6203]340 * @return BBox with same coordinates.
341 * @since 6203
342 */
343 public BBox toBBox() {
344 return new BBox(minLon, minLat, maxLon, maxLat);
345 }
[6830]346
[8846]347 @Override
348 public String toString() {
349 return "Bounds["+minLat+','+minLon+','+maxLat+','+maxLon+']';
[1169]350 }
[746]351
[12374]352 /**
353 * Converts this bounds to a human readable short string
354 * @param format The number format to use
355 * @return The string
356 */
[2717]357 public String toShortString(DecimalFormat format) {
[8846]358 return format.format(minLat) + ' '
[2805]359 + format.format(minLon) + " / "
[8846]360 + format.format(maxLat) + ' '
[2805]361 + format.format(maxLon);
[2717]362 }
363
[1169]364 /**
365 * @return Center of the bounding box.
366 */
[6509]367 public LatLon getCenter() {
[6830]368 if (crosses180thMeridian()) {
[6203]369 double lat = (minLat + maxLat) / 2;
370 double lon = (minLon + maxLon - 360.0) / 2;
[8510]371 if (lon < -180.0) {
[6203]372 lon += 360.0;
[4580]373 }
[6203]374 return new LatLon(lat, lon);
[4580]375 } else {
[6203]376 return new LatLon((minLat + maxLat) / 2, (minLon + maxLon) / 2);
[4580]377 }
[1169]378 }
379
380 /**
381 * Extend the bounds if necessary to include the given point.
[6203]382 * @param ll The point to include into these bounds
[1169]383 */
384 public void extend(LatLon ll) {
[6203]385 extend(ll.lat(), ll.lon());
386 }
[6830]387
[6203]388 /**
389 * Extend the bounds if necessary to include the given point [lat,lon].
390 * Good to use if you know coordinates to avoid creation of LatLon object.
391 * @param lat Latitude of point to include into these bounds
392 * @param lon Longitude of point to include into these bounds
393 * @since 6203
394 */
395 public void extend(final double lat, final double lon) {
396 if (lat < minLat) {
397 minLat = LatLon.roundToOsmPrecision(lat);
[2456]398 }
[6203]399 if (lat > maxLat) {
400 maxLat = LatLon.roundToOsmPrecision(lat);
[2805]401 }
[4580]402 if (crosses180thMeridian()) {
[6203]403 if (lon > maxLon && lon < minLon) {
404 if (Math.abs(lon - minLon) <= Math.abs(lon - maxLon)) {
405 minLon = LatLon.roundToOsmPrecision(lon);
[4580]406 } else {
[6203]407 maxLon = LatLon.roundToOsmPrecision(lon);
[4580]408 }
409 }
410 } else {
[6203]411 if (lon < minLon) {
412 minLon = LatLon.roundToOsmPrecision(lon);
[4580]413 }
[6203]414 if (lon > maxLon) {
415 maxLon = LatLon.roundToOsmPrecision(lon);
[4580]416 }
[2805]417 }
[1169]418 }
[2805]419
[12374]420 /**
421 * Extends this bounds to enclose an other bounding box
422 * @param b The other bounds to enclose
423 */
[2805]424 public void extend(Bounds b) {
[6203]425 extend(b.minLat, b.minLon);
426 extend(b.maxLat, b.maxLon);
[2805]427 }
[6069]428
[1169]429 /**
[6203]430 * Determines if the given point {@code ll} is within these bounds.
[12161]431 * <p>
432 * Points with unknown coordinates are always outside the coordinates.
[6203]433 * @param ll The lat/lon to check
434 * @return {@code true} if {@code ll} is within these bounds, {@code false} otherwise
[1169]435 */
436 public boolean contains(LatLon ll) {
[12161]437 // binary compatibility
438 return contains((ILatLon) ll);
439 }
440
441 /**
442 * Determines if the given point {@code ll} is within these bounds.
443 * <p>
444 * Points with unknown coordinates are always outside the coordinates.
445 * @param ll The lat/lon to check
446 * @return {@code true} if {@code ll} is within these bounds, {@code false} otherwise
[12162]447 * @since 12161
[12161]448 */
449 public boolean contains(ILatLon ll) {
450 if (!ll.isLatLonKnown()) {
451 return false;
452 }
[4580]453 if (ll.lat() < minLat || ll.lat() > maxLat)
[1169]454 return false;
[4580]455 if (crosses180thMeridian()) {
456 if (ll.lon() > maxLon && ll.lon() < minLon)
457 return false;
458 } else {
459 if (ll.lon() < minLon || ll.lon() > maxLon)
460 return false;
461 }
[1169]462 return true;
463 }
[2943]464
[4580]465 private static boolean intersectsLonCrossing(Bounds crossing, Bounds notCrossing) {
466 return notCrossing.minLon <= crossing.maxLon || notCrossing.maxLon >= crossing.minLon;
467 }
[6069]468
[2941]469 /**
470 * The two bounds intersect? Compared to java Shape.intersects, if does not use
[6830]471 * the interior but the closure. ("&gt;=" instead of "&gt;")
[9243]472 * @param b other bounds
473 * @return {@code true} if the two bounds intersect
[2941]474 */
475 public boolean intersects(Bounds b) {
[4580]476 if (b.maxLat < minLat || b.minLat > maxLat)
477 return false;
[6069]478
[4580]479 if (crosses180thMeridian() && !b.crosses180thMeridian()) {
480 return intersectsLonCrossing(this, b);
481 } else if (!crosses180thMeridian() && b.crosses180thMeridian()) {
482 return intersectsLonCrossing(b, this);
483 } else if (crosses180thMeridian() && b.crosses180thMeridian()) {
484 return true;
485 } else {
486 return b.maxLon >= minLon && b.minLon <= maxLon;
487 }
[2941]488 }
[1169]489
490 /**
[4580]491 * Determines if this Bounds object crosses the 180th Meridian.
492 * See http://wiki.openstreetmap.org/wiki/180th_meridian
493 * @return true if this Bounds object crosses the 180th Meridian.
494 */
495 public boolean crosses180thMeridian() {
496 return this.minLon > this.maxLon;
497 }
[6069]498
[4580]499 /**
[1169]500 * Converts the lat/lon bounding box to an object of type Rectangle2D.Double
501 * @return the bounding box to Rectangle2D.Double
502 */
503 public Rectangle2D.Double asRect() {
[10806]504 double w = getWidth();
[4580]505 return new Rectangle2D.Double(minLon, minLat, w, maxLat-minLat);
[1169]506 }
[2456]507
[10806]508 private double getWidth() {
509 return maxLon-minLon + (crosses180thMeridian() ? 360.0 : 0.0);
510 }
511
[12374]512 /**
513 * Gets the area of this bounds (in lat/lon space)
514 * @return The area
515 */
[2327]516 public double getArea() {
[10806]517 double w = getWidth();
[4580]518 return w * (maxLat - minLat);
[2327]519 }
[1169]520
[12374]521 /**
522 * Encodes this as a string so that it may be parsed using the {@link ParseMethod#MINLAT_MINLON_MAXLAT_MAXLON} order
523 * @param separator The separator
524 * @return The string encoded bounds
525 */
[2327]526 public String encodeAsString(String separator) {
[6822]527 StringBuilder sb = new StringBuilder();
[2805]528 sb.append(minLat).append(separator).append(minLon)
529 .append(separator).append(maxLat).append(separator)
530 .append(maxLon);
[2327]531 return sb.toString();
532 }
[2456]533
[4087]534 /**
535 * <p>Replies true, if this bounds are <em>collapsed</em>, i.e. if the min
536 * and the max corner are equal.</p>
[6069]537 *
[4087]538 * @return true, if this bounds are <em>collapsed</em>
539 */
540 public boolean isCollapsed() {
[6830]541 return Double.doubleToLongBits(minLat) == Double.doubleToLongBits(maxLat)
[6204]542 && Double.doubleToLongBits(minLon) == Double.doubleToLongBits(maxLon);
[4087]543 }
544
[11587]545 /**
546 * Determines if these bounds are out of the world.
547 * @return true if lat outside of range [-90,90] or lon outside of range [-180,180]
548 */
[4178]549 public boolean isOutOfTheWorld() {
550 return
[11587]551 !LatLon.isValidLat(minLat) ||
552 !LatLon.isValidLat(maxLat) ||
553 !LatLon.isValidLon(minLon) ||
554 !LatLon.isValidLon(maxLon);
[4178]555 }
556
[11587]557 /**
558 * Clamp the bounds to be inside the world.
559 */
[4178]560 public void normalize() {
[4580]561 minLat = LatLon.toIntervalLat(minLat);
562 maxLat = LatLon.toIntervalLat(maxLat);
563 minLon = LatLon.toIntervalLon(minLon);
564 maxLon = LatLon.toIntervalLon(maxLon);
[4178]565 }
566
[10806]567 /**
568 * Visit points along the edge of this bounds instance.
569 * @param projection The projection that should be used to determine how often the edge should be split along a given corner.
570 * @param visitor A function to call for the points on the edge.
571 * @since 10806
572 */
573 public void visitEdge(Projection projection, Consumer<LatLon> visitor) {
574 double width = getWidth();
575 double height = maxLat - minLat;
576 //TODO: Use projection to see if there is any need for doing this along each axis.
577 int splitX = Math.max((int) width / 10, 10);
578 int splitY = Math.max((int) height / 10, 10);
579
580 for (int step = 0; step < splitX; step++) {
581 visitor.accept(new LatLon(minLat, minLon + width * step / splitX));
582 }
583 for (int step = 0; step < splitY; step++) {
584 visitor.accept(new LatLon(minLat + height * step / splitY, maxLon));
585 }
586 for (int step = 0; step < splitX; step++) {
587 visitor.accept(new LatLon(maxLat, maxLon - width * step / splitX));
588 }
589 for (int step = 0; step < splitY; step++) {
590 visitor.accept(new LatLon(maxLat - height * step / splitY, minLon));
591 }
592 }
593
[2327]594 @Override
595 public int hashCode() {
[9371]596 return Objects.hash(minLat, minLon, maxLat, maxLon);
[2327]597 }
598
599 @Override
600 public boolean equals(Object obj) {
[9371]601 if (this == obj) return true;
602 if (obj == null || getClass() != obj.getClass()) return false;
603 Bounds bounds = (Bounds) obj;
604 return Double.compare(bounds.minLat, minLat) == 0 &&
605 Double.compare(bounds.minLon, minLon) == 0 &&
606 Double.compare(bounds.maxLat, maxLat) == 0 &&
607 Double.compare(bounds.maxLon, maxLon) == 0;
[2327]608 }
[71]609}
Note: See TracBrowser for help on using the repository browser.