Beginnings of new geometry library.

This commit is contained in:
Michael Bayne
2011-06-08 11:47:52 -07:00
commit e3c4be2602
14 changed files with 1304 additions and 0 deletions
+96
View File
@@ -0,0 +1,96 @@
//
// Pythagoras - a collection of geometry classes
// http://github.com/samskivert/pythagoras
package pythagoras.f;
import java.io.Serializable;
/**
* Represents a magnitude in two dimensions.
*/
public class Dimension implements IDimension, Serializable
{
/** The magnitude in the x-dimension. */
public float width;
/** The magnitude in the y-dimension. */
public float height;
/**
* Creates a dimension with magnitude (0, 0).
*/
public Dimension () {
this(0, 0);
}
/**
* Creates a dimension with the specified width and height.
*/
public Dimension (float width, float height) {
setSize(width, height);
}
/**
* Creates a dimension with width and height equal to the supplied dimension.
*/
public Dimension (IDimension d) {
this(d.getWidth(), d.getHeight());
}
/**
* Sets the magnitudes of this dimension to the specified width and height.
*/
public void setSize (float width, float height) {
this.width = width;
this.height = height;
}
/**
* Sets the magnitudes of this dimension to be equal to the supplied dimension.
*/
public void setSize (IDimension d) {
setSize(d.getWidth(), d.getHeight());
}
@Override // from interface IDimension
public float getWidth () {
return width;
}
@Override // from interface IDimension
public float getHeight () {
return height;
}
@Override // from interface IDimension
public Dimension clone () {
try {
return (Dimension)super.clone();
} catch (CloneNotSupportedException cnse) {
throw new AssertionError(cnse);
}
}
@Override
public int hashCode () {
return Float.floatToIntBits(width) ^ Float.floatToIntBits(height);
}
@Override
public boolean equals (Object obj) {
if (obj == this) {
return true;
}
if (obj instanceof Dimension) {
Dimension d = (Dimension)obj;
return (d.width == width && d.height == height);
}
return false;
}
@Override
public String toString () {
return Geometry.dimenToString(width, height);
}
}
+47
View File
@@ -0,0 +1,47 @@
//
// Pythagoras - a collection of geometry classes
// http://github.com/samskivert/pythagoras
package pythagoras.f;
/**
* Contains geometry routines that don't fit more nicely into specialized classes.
*/
public class Geometry
{
/**
* Returns the squared Euclidian distance between the specified two points.
*/
public static float distanceSq (float x1, float y1, float x2, float y2) {
x2 -= x1;
y2 -= y1;
return x2 * x2 + y2 * y2;
}
/**
* Returns the Euclidian distance between the specified two points.
*/
public static float distance (float x1, float y1, float x2, float y2) {
return (float)Math.sqrt(distanceSq(x1, y1, x2, y2));
}
/**
* Returns a string describing the supplied point, of the form <code>+x+y</code>,
* <code>+x-y</code>, <code>-x-y</code>, etc.
*/
public static String pointToString (float x, float y) {
StringBuilder buf = new StringBuilder();
if (x >= 0) buf.append("+");
buf.append(x);
if (y >= 0) buf.append("+");
buf.append(y);
return buf.toString();
}
/**
* Returns a string describing the supplied dimension, of the form <code>widthxheight</code>.
*/
public static String dimenToString (float width, float height) {
return width + "x" + height;
}
}
@@ -0,0 +1,26 @@
//
// Pythagoras - a collection of geometry classes
// http://github.com/samskivert/pythagoras
package pythagoras.f;
/**
* Provides read-only access to a {@link Dimension}.
*/
public interface IDimension extends Cloneable
{
/**
* Returns the magnitude in the x-dimension.
*/
float getWidth ();
/**
* Returns the magnitude in the y-dimension.
*/
float getHeight ();
/**
* Clones this dimension.
*/
Dimension clone ();
}
+46
View File
@@ -0,0 +1,46 @@
//
// Pythagoras - a collection of geometry classes
// http://github.com/samskivert/pythagoras
package pythagoras.f;
/**
* Provides read-only access to a {@link Point}.
*/
public interface IPoint extends Cloneable
{
/**
* Returns this point's x-coordinate.
*/
float getX ();
/**
* Returns this point's y-coordinate.
*/
float getY ();
/**
* Returns the squared Euclidian distance between this point and the specified point.
*/
float distanceSq (float px, float py);
/**
* Returns the squared Euclidian distance between this point and the supplied point.
*/
float distanceSq (IPoint p);
/**
* Returns the Euclidian distance between this point and the specified point.
*/
float distance (float px, float py);
/**
* Returns the Euclidian distance between this point and the supplied point.
*/
float distance (IPoint p);
/**
* Clones this point.
*/
Point clone ();
}
@@ -0,0 +1,99 @@
//
// Pythagoras - a collection of geometry classes
// http://github.com/samskivert/pythagoras
package pythagoras.f;
/**
* Provides read-only access to a {@link Rectangle}.
*/
public interface IRectangle extends Shape, Cloneable
{
/** The bitmask that indicates that a point lies to the left of this rectangle.
* See {@link #outcode}. */
int OUT_LEFT = 1;
/** The bitmask that indicates that a point lies above this rectangle. See {@link #outcode}. */
int OUT_TOP = 2;
/** The bitmask that indicates that a point lies to the right of this rectangle.
* See {@link #outcode}. */
int OUT_RIGHT = 4;
/** The bitmask that indicates that a point lies below this rectangle. See {@link #outcode}. */
int OUT_BOTTOM = 8;
/**
* Returns the x-coordinate of the rectangle's upper left corner.
*/
float getX ();
/**
* Returns the y-coordinate of the rectangle's upper left corner.
*/
float getY ();
/**
* Returns the width of the rectangle.
*/
float getWidth ();
/**
* Returns the height of the rectangle.
*/
float getHeight ();
/**
* Returns true if this rectangle does not have > 0 width and height.
*/
boolean isEmpty ();
/**
* Returns this rectangle's upper-left corner. Note that this constructs a new instance,
* because a {@link Rectangle} is not an {@link IPoint} and cannot efficiently masquerade as
* one.
*/
Point getLocation ();
/**
* Returns the size of this rectangle as a newly constructed dimension. Note that this
* constructs a new instance, because a {@link Rectangle} is not an {@link IDimension} and
* cannot efficiently masquerade as one.
*/
Dimension getSize ();
/**
* Returns the intersection of the specified rectangle and this rectangle (i.e. the largest
* rectangle contained in both this and the specified rectangle).
*/
Rectangle intersection (float rx, float ry, float rw, float rh);
/**
* Returns the intersection of the supplied rectangle and this rectangle (i.e. the largest
* rectangle contained in both this and the supplied rectangle).
*/
Rectangle intersection (IRectangle r);
/**
* Returns the union of the supplied rectangle and this rectangle (i.e. the smallest rectangle
* that contains both this and the supplied rectangle).
*/
Rectangle union (IRectangle r);
/**
* Returns a set of flags indicating where the specified point lies in relation to the bounds
* of this rectangle. See {@link #OUT_LEFT}, etc.
*/
int outcode (double px, double py);
/**
* Returns a set of flags indicating where the supplied point lies in relation to the bounds of
* this rectangle. See {@link #OUT_LEFT}, etc.
*/
int outcode (IPoint point);
/**
* Clones this rectangle.
*/
Rectangle clone ();
}
+131
View File
@@ -0,0 +1,131 @@
//
// Pythagoras - a collection of geometry classes
// http://github.com/samskivert/pythagoras
package pythagoras.f;
import java.io.Serializable;
/**
* Represents a point on a plane.
*/
public class Point implements IPoint, Serializable
{
/** The x-coordinate of the point. */
public float x;
/** The y-coordinate of the point. */
public float y;
/**
* Constructs a point at (0, 0).
*/
public Point () {
setLocation(0, 0);
}
/**
* Constructs a point at the specified coordinates.
*/
public Point (float x, float y) {
setLocation(x, y);
}
/**
* Constructs a point with coordinates equal to the supplied point.
*/
public Point (IPoint p) {
setLocation(p.getX(), p.getY());
}
/**
* Sets the coordinates of this point to be equal to those of the supplied point.
*/
public void setLocation (IPoint p) {
setLocation(p.getX(), p.getY());
}
/**
* Sets the coordinates of this point to the supplied values.
*/
public void setLocation (float x, float y) {
this.x = x;
this.y = y;
}
/**
* A synonym for {@link #setLocation}.
*/
public void move (float x, float y) {
setLocation(x, y);
}
/**
* Translates this point by the specified offset.
*/
public void translate (float dx, float dy) {
x += dx;
y += dy;
}
@Override // from interface IPoint
public float getX () {
return x;
}
@Override // from interface IPoint
public float getY () {
return y;
}
@Override // from interface IPoint
public float distanceSq (float px, float py) {
return Geometry.distanceSq(x, y, px, py);
}
@Override // from interface IPoint
public float distanceSq (IPoint p) {
return Geometry.distanceSq(x, y, p.getX(), p.getY());
}
@Override // from interface IPoint
public float distance (float px, float py) {
return Geometry.distance(x, y, px, py);
}
@Override // from interface IPoint
public float distance (IPoint p) {
return Geometry.distance(x, y, p.getX(), p.getY());
}
@Override // from interface IPoint
public Point clone () {
try {
return (Point)super.clone();
} catch (CloneNotSupportedException cnse) {
throw new AssertionError(cnse);
}
}
@Override
public boolean equals (Object obj) {
if (obj == this) {
return true;
}
if (obj instanceof Point) {
Point p = (Point)obj;
return x == p.x && y == p.y;
}
return false;
}
@Override
public int hashCode () {
return Float.floatToIntBits(x) ^ Float.floatToIntBits(y);
}
@Override
public String toString () {
return Geometry.pointToString(x, y);
}
}
+327
View File
@@ -0,0 +1,327 @@
//
// Pythagoras - a collection of geometry classes
// http://github.com/samskivert/pythagoras
package pythagoras.f;
import java.io.Serializable;
/**
* Represents an area in two dimensions.
*/
public class Rectangle implements IRectangle, Serializable
{
/** The x-coordinate of the rectangle's upper left corner. */
public float x;
/** The y-coordinate of the rectangle's upper left corner. */
public float y;
/** The width of the rectangle. */
public float width;
/** The height of the rectangle. */
public float height;
/**
* Constructs a rectangle at (0,0) and with dimensions (0,0).
*/
public Rectangle () {
setBounds(0, 0, 0, 0);
}
/**
* Constructs a rectangle with the supplied upper-left corner and dimensions (0,0).
*/
public Rectangle (Point p) {
setBounds(p.x, p.y, 0, 0);
}
/**
* Constructs a rectangle with upper-left corner at (0,) and the supplied dimensions.
*/
public Rectangle (Dimension d) {
setBounds(0, 0, d.width, d.height);
}
/**
* Constructs a rectangle with upper-left corner at the supplied point and with the supplied
* dimensions.
*/
public Rectangle (Point p, Dimension d) {
setBounds(p.x, p.y, d.width, d.height);
}
/**
* Constructs a rectangle with the specified upper-left corner and dimensions.
*/
public Rectangle (float x, float y, float width, float height) {
setBounds(x, y, width, height);
}
/**
* Constructs a rectangle with bounds equal to the supplied rectangle.
*/
public Rectangle (Rectangle r) {
setBounds(r.x, r.y, r.width, r.height);
}
/**
* Sets the size of this rectangle to the specified dimensions.
*/
public void setSize (float width, float height) {
this.width = width;
this.height = height;
}
/**
* Sets the size of this rectangle to the supplied dimensions.
*/
public void setSize (Dimension d) {
setSize(d.width, d.height);
}
/**
* Sets the upper-left corner of this rectangle to the specified point.
*/
public void setLocation (float x, float y) {
this.x = x;
this.y = y;
}
/**
* Sets the upper-left corner of this rectangle to the supplied point.
*/
public void setLocation (IPoint p) {
setLocation(p.getX(), p.getY());
}
/**
* Sets the bounds of this rectangle to the specified bounds.
*/
public void setBounds (float x, float y, float width, float height) {
this.x = x;
this.y = y;
this.height = height;
this.width = width;
}
/**
* Sets the bounds of this rectangle to those of the supplied rectangle.
*/
public void setBounds (IRectangle r) {
setBounds(r.getX(), r.getY(), r.getWidth(), r.getHeight());
}
/**
* Grows the bounds of this rectangle by the specified amount (i.e. the upper-left corner moves
* by the specified amount in the negative x and y direction and the width and height grow by
* twice the specified amount).
*/
public void grow (float dx, float dy) {
x -= dx;
y -= dy;
width += dx + dx;
height += dy + dy;
}
/**
* Translates the upper-left corner of this rectangle by the specified amount.
*/
public void translate (float mx, float my) {
x += mx;
y += my;
}
/**
* Expands the bounds of this rectangle to contain the specified point.
*/
public void add (float px, float py) {
float x1 = Math.min(x, px);
float x2 = Math.max(x + width, px);
float y1 = Math.min(y, py);
float y2 = Math.max(y + height, py);
setBounds(x1, y1, x2 - x1, y2 - y1);
}
/**
* Expands the bounds of this rectangle to contain the supplied point.
*/
public void add (IPoint p) {
add(p.getX(), p.getY());
}
/**
* Expands the bounds of this rectangle to contain the supplied rectangle.
*/
public void add (IRectangle r) {
float x1 = Math.min(x, r.getX());
float x2 = Math.max(x + width, r.getX() + r.getWidth());
float y1 = Math.min(y, r.getY());
float y2 = Math.max(y + height, r.getY() + r.getHeight());
setBounds(x1, y1, x2 - x1, y2 - y1);
}
@Override // from interface IRectangle
public float getX ()
{
return x;
}
@Override // from interface IRectangle
public float getY ()
{
return y;
}
@Override // from interface IRectangle
public float getWidth ()
{
return width;
}
@Override // from interface IRectangle
public float getHeight ()
{
return height;
}
@Override // from interface IRectangle
public boolean isEmpty () {
return width <= 0 || height <= 0;
}
@Override // from interface IRectangle
public Point getLocation () {
return new Point(x, y);
}
@Override // from interface IRectangle
public Dimension getSize () {
return new Dimension(width, height);
}
@Override // from interface IRectangle
public Rectangle intersection (float rx, float ry, float rw, float rh) {
float x1 = Math.max(x, rx);
float y1 = Math.max(y, ry);
float x2 = Math.min(x + width, rx + rw);
float y2 = Math.min(y + height, ry + rh);
return new Rectangle(x1, y1, x2 - x1, y2 - y1);
}
@Override // from interface IRectangle
public Rectangle intersection (IRectangle r) {
return intersection(r.getX(), r.getY(), r.getWidth(), r.getHeight());
}
@Override // from interface IRectangle
public Rectangle union (IRectangle r) {
Rectangle rect = new Rectangle(this);
rect.add(r);
return rect;
}
@Override // from interface IRectangle
public int outcode (double px, double py) {
int code = 0;
if (width <= 0) {
code |= OUT_LEFT | OUT_RIGHT;
} else if (px < x) {
code |= OUT_LEFT;
} else if (px > x + width) {
code |= OUT_RIGHT;
}
if (height <= 0) {
code |= OUT_TOP | OUT_BOTTOM;
} else if (py < y) {
code |= OUT_TOP;
} else if (py > y + height) {
code |= OUT_BOTTOM;
}
return code;
}
@Override // from interface IRectangle
public int outcode (IPoint p) {
return outcode(p.getX(), p.getY());
}
@Override // from interface IRectangle
public Rectangle clone () {
try {
return (Rectangle)super.clone();
} catch (CloneNotSupportedException cnse) {
throw new AssertionError(cnse);
}
}
@Override // from interface Shape
public boolean contains (float px, float py) {
if (isEmpty()) {
return false;
}
if (px < x || py < y) {
return false;
}
px -= x;
py -= y;
return px < width && py < height;
}
@Override // from interface Shape
public boolean contains (IPoint p) {
return contains(p.getX(), p.getY());
}
@Override // from interface Shape
public boolean contains (float rx, float ry, float rw, float rh) {
return contains(rx, ry) && contains(rx + rw - 1, ry + rh - 1);
}
@Override // from interface Shape
public boolean contains (IRectangle r) {
return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight());
}
@Override // from interface Shape
public boolean intersects (float rx, float ry, float rw, float rh) {
return !intersection(rx, ry, rw, rh).isEmpty(); // TODO: don't create garbage
}
@Override // from interface Shape
public boolean intersects (IRectangle r) {
return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight());
}
@Override // from interface Shape
public IRectangle getBounds () {
return this;
}
@Override
public boolean equals (Object obj) {
if (obj == this) {
return true;
}
if (obj instanceof Rectangle) {
Rectangle r = (Rectangle)obj;
return r.x == x && r.y == y && r.width == width && r.height == height;
}
return false;
}
@Override
public int hashCode () {
return Float.floatToIntBits(x) ^ Float.floatToIntBits(y) ^
Float.floatToIntBits(width) ^ Float.floatToIntBits(height);
}
@Override
public String toString () {
return Geometry.dimenToString(width, height) + Geometry.pointToString(x, y);
}
}
+63
View File
@@ -0,0 +1,63 @@
//
// Pythagoras - a collection of geometry classes
// http://github.com/samskivert/pythagoras
package pythagoras.f;
/**
* An interface provided by all shapes.
*/
public interface Shape
{
/**
* Returns true if this shape contains the specified point.
*/
boolean contains (float x, float y);
/**
* Returns true if this shape contains the supplied point.
*/
boolean contains (IPoint point);
/**
* Returns true if this shape completely contains the specified rectangle.
*/
boolean contains (float x, float y, float w, float h);
/**
* Returns true if this shape completely contains the supplied rectangle.
*/
boolean contains (IRectangle r);
/**
* Returns true if this shape intersects the specified rectangle.
*/
boolean intersects (float x, float y, float w, float h);
/**
* Returns true if this shape intersects the supplied rectangle.
*/
boolean intersects (IRectangle r);
/**
* Returns the bounding rectangle for this shape.
*/
IRectangle getBounds ();
// /**
// * Returns an iterator over the path described by this shape.
// *
// * @param at if supplied, the points in the path are transformed using this.
// */
// PathIterator getPathIterator (AffineTransform at);
// /**
// * Returns an iterator over the path described by this shape.
// *
// * @param at if supplied, the points in the path are transformed using this.
// * @param flatness when approximating curved segments with lines, this controls the maximum
// * distance the lines are allowed to deviate from the approximated curve, thus a higher
// * flatness value generally allows for a path with fewer segments.
// */
// PathIterator getPathIterator (AffineTransform at, float flatness);
}