/**
* Copyright (c) 2009, iPlant Collaborative, Texas Advanced Computing Center This software is licensed
* under the CC-GNU GPL version 2.0 or later. License: http://creativecommons.org/licenses/GPL/2.0/
*/
package org.iplantc.phyloviewer.shared.math;
import com.google.gwt.user.client.rpc.IsSerializable;
public class Box2D implements IsSerializable
{
private Vector2 min;
private Vector2 max;
private static Vector2 getDefaultMinValue()
{
return new Vector2(Double.MAX_VALUE, Double.MAX_VALUE);
}
private static Vector2 getDefaultMaxValue()
{
return new Vector2(Double.MIN_VALUE, Double.MIN_VALUE);
}
/**
* Create a box with invalid min and max corners.
*/
public Box2D()
{
min = getDefaultMinValue();
max =getDefaultMaxValue();
}
/**
* Create a bounding box.
*
* @param Lower left corner of box.
* @param Upper right corner of box.
*/
public Box2D(Vector2 min, Vector2 max)
{
setMin(min);
setMax(max);
}
/**
* Clone this box
*/
public Box2D clone()
{
Vector2 min = this.getMin();
if(min == null)
{
min = getDefaultMinValue();
}
else
{
min = min.clone();
}
Vector2 max = this.getMax();
if(max == null)
{
max = getDefaultMaxValue();
}
else
{
max = max.clone();
}
return new Box2D(min, max);
}
public Boolean valid()
{
return max.getX() >= min.getX() && max.getY() >= min.getY();
}
public Vector2 getMin()
{
return min;
}
public void setMin(Vector2 min)
{
if(min == this.max)
{
// we don't want these to be the same object, or mutators with change both at once
min = new Vector2(min.getX(), min.getY());
}
this.min = min;
}
public Vector2 getMax()
{
return max;
}
public void setMax(Vector2 max)
{
if(max == this.min)
{
// we don't want these to be the same object, or mutators with change both at once
max = new Vector2(max.getX(), max.getY());
}
this.max = max;
}
public void expandBy(Vector2 v)
{
if(v.getX() < min.getX())
min.setX(v.getX());
if(v.getX() > max.getX())
max.setX(v.getX());
if(v.getY() < min.getY())
min.setY(v.getY());
if(v.getY() > max.getY())
max.setY(v.getY());
}
public void expandBy(Box2D bb)
{
if(false == bb.valid())
return;
if(bb.getMin().getX() < min.getX())
min.setX(bb.getMin().getX());
if(bb.getMax().getX() > max.getX())
max.setX(bb.getMax().getX());
if(bb.getMin().getY() < min.getY())
min.setY(bb.getMin().getY());
if(bb.getMax().getY() > max.getY())
max.setY(bb.getMax().getY());
}
public void expandBy(double d)
{
min.setX(min.getX() - d);
min.setY(min.getY() - d);
max.setX(max.getX() + d);
max.setY(max.getY() + d);
}
// Return true if the given box intersects this one.
public boolean intersects(Box2D bb)
{
return Math.max(min.getX(), bb.getMin().getX()) <= Math.min(max.getX(), bb.getMax().getX())
&& Math.max(min.getY(), bb.getMin().getY()) <= Math.min(max.getY(), bb.getMax().getY());
}
public boolean contains(Vector2 position)
{
return this.valid()
&& (position.getX() >= this.getMin().getX() && position.getX() <= this.getMax().getX()
&& position.getY() >= this.getMin().getY() && position.getY() <= this.getMax()
.getY());
}
public Vector2 getCenter()
{
double x = (min.getX() + max.getX()) / 2.0;
double y = (min.getY() + max.getY()) / 2.0;
return new Vector2(x, y);
}
public double getWidth()
{
return max.getX() - min.getX();
}
public double getHeight()
{
return max.getY() - min.getY();
}
public String toString()
{
return "[" + min.toString() + ", " + max.toString() + "]";
}
/**
* @return the box defined by the given corners (any two opposite corners of the box)
*/
public static Box2D createBox(Vector2 v0, Vector2 v1)
{
Box2D box = new Box2D(v0, v0);
box.expandBy(v1);
return box;
}
public String toJSON()
{
return "{\"min\":" + min.toJSON() + ",\"max\":" + max.toJSON() + "}";
}
}