ucar.unidata.geoloc.ProjectionRect Maven / Gradle / Ivy
Show all versions of cdm Show documentation
/*
* Copyright 1998-2014 University Corporation for Atmospheric Research/Unidata
*
* Portions of this software were developed by the Unidata Program at the
* University Corporation for Atmospheric Research.
*
* Access and use of this software shall impose the following obligations
* and understandings on the user. The user is granted the right, without
* any fee or cost, to use, copy, modify, alter, enhance and distribute
* this software, and any derivative works thereof, and its supporting
* documentation for any purpose whatsoever, provided that this entire
* notice appears in all copies of the software, derivative works and
* supporting documentation. Further, UCAR requests that the user credit
* UCAR/Unidata in any publications that result from the use of this
* software or in any product that includes this software. The names UCAR
* and/or Unidata, however, may not be used in any advertising or publicity
* to endorse or promote any products or commercial entity unless specific
* written permission is obtained from UCAR/Unidata. The user also
* understands that UCAR/Unidata is not obligated to provide the user with
* any support, consulting, training or assistance of any kind with regard
* to the use, operation and performance of this software nor to provide
* the user with any updates, revisions, new versions or "bug fixes."
*
* THIS SOFTWARE IS PROVIDED BY UCAR/UNIDATA "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL UCAR/UNIDATA BE LIABLE FOR ANY SPECIAL,
* INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
* WITH THE ACCESS, USE OR PERFORMANCE OF THIS SOFTWARE.
*/
package ucar.unidata.geoloc;
import com.google.common.math.DoubleMath;
import ucar.unidata.util.Format;
import java.io.*;
/**
* Bounding box for ProjectionPoint's.
* Note that getX() getY() really means getMinX(), getMinY(), rather than
* "upper left point" of the rectangle.
*
* @author John Caron
*/
public class ProjectionRect implements java.io.Serializable {
private double x, y, width, height;
/**
* default constructor, initialized to center (0,0) and width (10000, 10000)
*/
public ProjectionRect() {
this(-5000, -5000, 5000, 5000);
}
/**
* Construct a MapArea from any two opposite corner points.
*
* @param corner1 a corner.
* @param corner2 the opposite corner.
*/
public ProjectionRect(ProjectionPoint corner1, ProjectionPoint corner2) {
this(corner1.getX(), corner1.getY(), corner2.getX(), corner2.getY());
}
/**
* Copy Constructor
*
* @param r rectangle to copy
*/
public ProjectionRect(ProjectionRect r) {
this(r.getMinX(), r.getMinY(), r.getMaxX(), r.getMaxY());
}
/**
* construct a MapArea from any two opposite corner points
*
* @param x1 x coord of any corner of the bounding box
* @param y1 y coord of the same corner as x1
* @param x2 x coord of opposite corner from x1,y1
* @param y2 y coord of same corner as x2
*/
public ProjectionRect(double x1, double y1, double x2, double y2) {
double wx0 = 0.5 * (x1 + x2);
double wy0 = 0.5 * (y1 + y2);
double width = Math.abs(x1 - x2);
double height = Math.abs(y1 - y2);
setRect(wx0 - width / 2, wy0 - height / 2, width, height);
}
public double getX() {
return x;
}
public double getY() {
return y;
}
public double getWidth() {
return width;
}
public double getHeight() {
return height;
}
////////////////////////////////////////////////////
// taken from java.awt.geom.Rectangle2D, removed because awt missing on android
/**
* Returns the smallest X coordinate of the framing
* rectangle of the Shape
in double
* precision.
*
* @return the smallest X coordinate of the framing
* rectangle of the Shape
.
* @since 1.2
*/
public double getMinX() {
return getX();
}
/**
* Returns the smallest Y coordinate of the framing
* rectangle of the Shape
in double
* precision.
*
* @return the smallest Y coordinate of the framing
* rectangle of the Shape
.
* @since 1.2
*/
public double getMinY() {
return getY();
}
/**
* Returns the largest X coordinate of the framing
* rectangle of the Shape
in double
* precision.
*
* @return the largest X coordinate of the framing
* rectangle of the Shape
.
* @since 1.2
*/
public double getMaxX() {
return getX() + getWidth();
}
/**
* Returns the largest Y coordinate of the framing
* rectangle of the Shape
in double
* precision.
*
* @return the largest Y coordinate of the framing
* rectangle of the Shape
.
* @since 1.2
*/
public double getMaxY() {
return getY() + getHeight();
}
/**
* Returns the X coordinate of the center of the framing
* rectangle of the Shape
in double
* precision.
* @return the X coordinate of the center of the framing rectangle
* of the Shape
.
* @since 1.2
*/
public double getCenterX() {
return getX() + getWidth() / 2.0;
}
/**
* Returns the Y coordinate of the center of the framing
* rectangle of the Shape
in double
* precision.
* @return the Y coordinate of the center of the framing rectangle
* of the Shape
.
* @since 1.2
*/
public double getCenterY() {
return getY() + getHeight() / 2.0;
}
/**
* Adds a Rectangle2D
object to this
* Rectangle2D
. The resulting Rectangle2D
* is the union of the two Rectangle2D
objects.
* @param r the Rectangle2D
to add to this
* Rectangle2D
.
* @since 1.2
*/
public void add(ProjectionRect r) {
double x1 = Math.min(getMinX(), r.getMinX());
double x2 = Math.max(getMaxX(), r.getMaxX());
double y1 = Math.min(getMinY(), r.getMinY());
double y2 = Math.max(getMaxY(), r.getMaxY());
setRect(x1, y1, x2 - x1, y2 - y1);
}
/**
* Adds a point, specified by the double precision arguments
* newx
and newy
, to this
* Rectangle2D
. The resulting Rectangle2D
* is the smallest Rectangle2D
that
* contains both the original Rectangle2D
and the
* specified point.
*
* After adding a point, a call to contains
with the
* added point as an argument does not necessarily return
* true
. The contains
method does not
* return true
for points on the right or bottom
* edges of a rectangle. Therefore, if the added point falls on
* the left or bottom edge of the enlarged rectangle,
* contains
returns false
for that point.
* @param newx the X coordinate of the new point
* @param newy the Y coordinate of the new point
* @since 1.2
*/
public void add(double newx, double newy) {
double x1 = Math.min(getMinX(), newx);
double x2 = Math.max(getMaxX(), newx);
double y1 = Math.min(getMinY(), newy);
double y2 = Math.max(getMaxY(), newy);
setRect(x1, y1, x2 - x1, y2 - y1);
}
/**
* Adds the Point2D
object pt
to this
* Rectangle2D
.
* The resulting Rectangle2D
is the smallest
* Rectangle2D
that contains both the original
* Rectangle2D
and the specified Point2D
.
*
* After adding a point, a call to contains
with the
* added point as an argument does not necessarily return
* true
. The contains
* method does not return true
for points on the right
* or bottom edges of a rectangle. Therefore, if the added point falls
* on the left or bottom edge of the enlarged rectangle,
* contains
returns false
for that point.
* @param pt the new Point2D
to add to this
* Rectangle2D
.
* @since 1.2
*/
public void add(ProjectionPoint pt) {
add(pt.getX(), pt.getY());
}
public boolean isEmpty() {
return (width <= 0.0) || (height <= 0.0);
}
public boolean intersects(ProjectionRect r) {
return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight());
}
public boolean intersects(double x, double y, double w, double h) {
if (isEmpty() || w <= 0 || h <= 0) {
return false;
}
double x0 = getX();
double y0 = getY();
return (x + w > x0 &&
y + h > y0 &&
x < x0 + getWidth() &&
y < y0 + getHeight());
}
/**
* Intersects the pair of specified source Rectangle2D
* objects and puts the result into the specified destination
* Rectangle2D
object. One of the source rectangles
* can also be the destination to avoid creating a third Rectangle2D
* object, but in this case the original points of this source
* rectangle will be overwritten by this method.
* @param src1 the first of a pair of Rectangle2D
* objects to be intersected with each other
* @param src2 the second of a pair of Rectangle2D
* objects to be intersected with each other
* @param dest the Rectangle2D
that holds the
* results of the intersection of src1
and
* src2
* @since 1.2
*/
public static void intersect(ProjectionRect src1, ProjectionRect src2, ProjectionRect dest) {
double x1 = Math.max(src1.getMinX(), src2.getMinX());
double y1 = Math.max(src1.getMinY(), src2.getMinY());
double x2 = Math.min(src1.getMaxX(), src2.getMaxX());
double y2 = Math.min(src1.getMaxY(), src2.getMaxY());
dest.setRect(x1, y1, x2 - x1, y2 - y1);
}
/**
* Returns {@code true} if this bounding box contains {@code point}.
*
* @param point a point in projection coordinates.
* @return {@code true} if this bounding box contains {@code point}.
*/
public boolean contains(ProjectionPoint point) {
return DoubleMath.fuzzyCompare(point.getX(), getMinX(), 1e-6) >= 0 &&
DoubleMath.fuzzyCompare(point.getX(), getMaxX(), 1e-6) <= 0 &&
DoubleMath.fuzzyCompare(point.getY(), getMinY(), 1e-6) >= 0 &&
DoubleMath.fuzzyCompare(point.getY(), getMaxY(), 1e-6) <= 0;
}
/////////////////////////////////////////////////////
/**
* Get the Lower Right Point
*
* @return the Lower Right Point
*/
public ProjectionPoint getLowerRightPoint() {
return new ProjectionPointImpl(getMaxPoint().getX(), getMinPoint().getY());
}
/**
* Get the Upper Left Point (same as getMaxPoint)
*
* @return the Upper Left Point
*/
public ProjectionPoint getUpperRightPoint() {
return getMaxPoint();
}
/**
* Get the Lower Right Point (same as getMinPoint)
*
* @return the Lower Right Point
*/
public ProjectionPoint getLowerLeftPoint() {
return getMinPoint();
}
/**
* Get the Upper Left Point
*
* @return the Upper Left Point
*/
public ProjectionPoint getUpperLeftPoint() {
return new ProjectionPointImpl(getMinPoint().getX(),
getMaxPoint().getY());
}
/**
* Get the minimum corner of the bounding box.
*
* @return minimum corner of the bounding box
*/
public ProjectionPoint getMinPoint() {
return new ProjectionPointImpl(getX(), getY());
}
/**
* Get the maximum corner of the bounding box.
*
* @return maximum corner of the bounding box
*/
public ProjectionPoint getMaxPoint() {
return new ProjectionPointImpl(getX() + getWidth(),
getY() + getHeight());
}
/**
* Get a String representation of this object.
*
* @return a String representation of this object.
*/
public String toString() {
return "min: " + Format.d(getX(), 3) + " " + Format.d(getY(), 3)
+ " size: " + Format.d(getWidth(), 3) + " "
+ Format.d(getHeight(), 3);
}
public String toString2() {
return "min: " + Format.d(getX(), 3) + " " + Format.d(getY(), 3)
+ " max: " + Format.d(getX() + getWidth(), 3) + " " + Format.d(getY() + getHeight(), 3);
}
// bean serialization
/**
* set minimum X
*
* @param x minimum x
*/
public void setX(double x) {
setRect(x, getY(), getWidth(), getHeight());
}
/**
* set minimum Y
*
* @param y minimum y
*/
public void setY(double y) {
setRect(getX(), y, getWidth(), getHeight());
}
/**
* set X width
*
* @param w x width
*/
public void setWidth(double w) {
setRect(getX(), getY(), w, getHeight());
}
/**
* set Y height
*
* @param h Y height
*/
public void setHeight(double h) {
setRect(getX(), getY(), getWidth(), h);
}
public void setRect(ProjectionRect r) {
setRect(r.getX(), r.getY(), r.getWidth(), r.getHeight());
}
public void setRect(double x, double y, double w, double h) {
this.x = x;
this.y = y;
this.width = w;
this.height = h;
}
// serialization
/**
* Read the object from the input stream of the serialized object
*
* @param s stream to read
* @throws ClassNotFoundException couldn't file the class
* @throws IOException Problem reading from stream
*/
private void readObject(ObjectInputStream s)
throws IOException, ClassNotFoundException {
double x = s.readDouble();
double y = s.readDouble();
double w = s.readDouble();
double h = s.readDouble();
setRect(x, y, w, h);
}
/**
* Wrtie the object to the output stream
*
* @param s stream to write
* @throws IOException Problem writing to stream
*/
private void writeObject(ObjectOutputStream s) throws IOException {
s.writeDouble(getX());
s.writeDouble(getY());
s.writeDouble(getWidth());
s.writeDouble(getHeight());
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ProjectionRect that = (ProjectionRect) o;
if (Double.compare(that.height, height) != 0) return false;
if (Double.compare(that.width, width) != 0) return false;
if (Double.compare(that.x, x) != 0) return false;
if (Double.compare(that.y, y) != 0) return false;
return true;
}
@Override
public int hashCode() {
int result;
long temp;
temp = Double.doubleToLongBits(x);
result = (int) (temp ^ (temp >>> 32));
temp = Double.doubleToLongBits(y);
result = 31 * result + (int) (temp ^ (temp >>> 32));
temp = Double.doubleToLongBits(width);
result = 31 * result + (int) (temp ^ (temp >>> 32));
temp = Double.doubleToLongBits(height);
result = 31 * result + (int) (temp ^ (temp >>> 32));
return result;
}
}