Added version of getTile() that takes a rectangle into which to write the results.

git-svn-id: svn+ssh://src.earth.threerings.net/nenya/trunk@282 ed5b42cb-e716-0410-a449-f6a68f950b19
This commit is contained in:
Michael Bayne
2007-08-03 21:10:48 +00:00
parent 205d57a7fe
commit bbd5dd284e
+58 -63
View File
@@ -40,14 +40,12 @@ public class GeomUtil
*/ */
public static int dot (Point v1s, Point v1e, Point v2s, Point v2e) public static int dot (Point v1s, Point v1e, Point v2s, Point v2e)
{ {
return ((v1e.x - v1s.x) * (v2e.x - v2s.x) + return ((v1e.x - v1s.x) * (v2e.x - v2s.x) + (v1e.y - v1s.y) * (v2e.y - v2s.y));
(v1e.y - v1s.y) * (v2e.y - v2s.y));
} }
/** /**
* Computes and returns the dot product of the two vectors. See * Computes and returns the dot product of the two vectors. See {@link
* {@link #dot(Point,Point,Point,Point)} for an explanation of the * #dot(Point,Point,Point,Point)} for an explanation of the arguments
* arguments
*/ */
public static int dot (int v1sx, int v1sy, int v1ex, int v1ey, public static int dot (int v1sx, int v1sy, int v1ex, int v1ey,
int v2sx, int v2sy, int v2ex, int v2ey) int v2sx, int v2sy, int v2ex, int v2ey)
@@ -56,9 +54,8 @@ public class GeomUtil
} }
/** /**
* Computes and returns the dot product of the two vectors. The * Computes and returns the dot product of the two vectors. The vectors are assumed to start
* vectors are assumed to start with the same coordinate and end with * with the same coordinate and end with different coordinates.
* different coordinates.
* *
* @param vs the starting point of both vectors. * @param vs the starting point of both vectors.
* @param v1e the ending point of the first vector. * @param v1e the ending point of the first vector.
@@ -66,40 +63,35 @@ public class GeomUtil
*/ */
public static int dot (Point vs, Point v1e, Point v2e) public static int dot (Point vs, Point v1e, Point v2e)
{ {
return ((v1e.x - vs.x) * (v2e.x - vs.x) + return ((v1e.x - vs.x) * (v2e.x - vs.x) + (v1e.y - vs.y) * (v2e.y - vs.y));
(v1e.y - vs.y) * (v2e.y - vs.y));
} }
/** /**
* Computes and returns the dot product of the two vectors. * Computes and returns the dot product of the two vectors. See {@link
* See {@link #dot(Point,Point,Point)} for an explanation of the * #dot(Point,Point,Point)} for an explanation of the arguments
* arguments
*/ */
public static int dot (int vsx, int vsy, int v1ex, int v1ey, public static int dot (int vsx, int vsy, int v1ex, int v1ey, int v2ex, int v2ey)
int v2ex, int v2ey)
{ {
return ((v1ex - vsx) * (v2ex - vsx) + (v1ey - vsy) * (v2ey - vsy)); return ((v1ex - vsx) * (v2ex - vsx) + (v1ey - vsy) * (v2ey - vsy));
} }
/** /**
* Computes the point nearest to the specified point <code>p3</code> * Computes the point nearest to the specified point <code>p3</code> on the line defined by the
* on the line defined by the two points <code>p1</code> and * two points <code>p1</code> and <code>p2</code>. The computed point is stored into
* <code>p2</code>. The computed point is stored into <code>n</code>. * <code>n</code>. <em>Note:</em> <code>p1</code> and <code>p2</code> must not be coincident.
* <em>Note:</em> <code>p1</code> and <code>p2</code> must not be
* coincident.
* *
* @param p1 one point on the line. * @param p1 one point on the line.
* @param p2 another point on the line (not equal to <code>p1</code>). * @param p2 another point on the line (not equal to <code>p1</code>).
* @param p3 the point to which we wish to be most near. * @param p3 the point to which we wish to be most near.
* @param n the point on the line defined by <code>p1</code> and * @param n the point on the line defined by <code>p1</code> and <code>p2</code> that is
* <code>p2</code> that is nearest to <code>p</code>. * nearest to <code>p</code>.
* *
* @return the point object supplied via <code>n</code>. * @return the point object supplied via <code>n</code>.
*/ */
public static Point nearestToLine (Point p1, Point p2, Point p3, Point n) public static Point nearestToLine (Point p1, Point p2, Point p3, Point n)
{ {
// see http://astronomy.swin.edu.au/~pbourke/geometry/pointline/ // see http://astronomy.swin.edu.au/~pbourke/geometry/pointline/ for a (not very good)
// for a (not very good) explanation of the math // explanation of the math
int Ax = p2.x - p1.x, Ay = p2.y - p1.y; int Ax = p2.x - p1.x, Ay = p2.y - p1.y;
float u = (p3.x - p1.x) * Ax + (p3.y - p1.y) * Ay; float u = (p3.x - p1.x) * Ax + (p3.y - p1.y) * Ay;
u /= (Ax * Ax + Ay * Ay); u /= (Ax * Ax + Ay * Ay);
@@ -109,25 +101,21 @@ public class GeomUtil
} }
/** /**
* Calculate the intersection of two lines. Either line may be * Calculate the intersection of two lines. Either line may be considered as a line segment,
* considered as a line segment, and the intersecting point * and the intersecting point is only considered valid if it lies upon the segment. Note that
* is only considered valid if it lies upon the segment. * Point extends Point2D.
* Note that Point extends Point2D.
* *
* @param p1 and p2 the coordinates of the first line. * @param p1 and p2 the coordinates of the first line.
* @param seg1 if the first line should be considered a segment. * @param seg1 if the first line should be considered a segment.
* @param p3 and p4 the coordinates of the second line. * @param p3 and p4 the coordinates of the second line.
* @param seg2 if the second line should be considered a segment. * @param seg2 if the second line should be considered a segment.
* @param result the point that will be filled in with the intersecting * @param result the point that will be filled in with the intersecting point.
* point.
* *
* @return true if result was filled in, or false if the lines * @return true if result was filled in, or false if the lines are parallel or the point of
* are parallel or the point of intersection lies outside of a * intersection lies outside of a segment.
* segment.
*/ */
public static boolean lineIntersection ( public static boolean lineIntersection (Point2D p1, Point2D p2, boolean seg1,
Point2D p1, Point2D p2, boolean seg1, Point2D p3, Point2D p4, boolean seg2, Point2D result)
Point2D p3, Point2D p4, boolean seg2, Point2D result)
{ {
// see http://astronomy.swin.edu.au/~pbourke/geometry/lineline2d/ // see http://astronomy.swin.edu.au/~pbourke/geometry/lineline2d/
double y43 = p4.getY() - p3.getY(); double y43 = p4.getY() - p3.getY();
@@ -160,11 +148,10 @@ public class GeomUtil
} }
/** /**
* Returns less than zero if <code>p2</code> is on the left hand side * Returns less than zero if <code>p2</code> is on the left hand side of the line created by
* of the line created by <code>p1</code> and <code>theta</code> and * <code>p1</code> and <code>theta</code> and greater than zero if it is on the right hand
* greater than zero if it is on the right hand side. In theory, it * side. In theory, it will return zero if the point is on the line, but due to rounding errors
* will return zero if the point is on the line, but due to rounding * it almost always decides that it's not exactly on the line.
* errors it almost always decides that it's not exactly on the line.
* *
* @param p1 the point on the line whose side we're checking. * @param p1 the point on the line whose side we're checking.
* @param theta the (logical) angle defining the line. * @param theta the (logical) angle defining the line.
@@ -177,17 +164,16 @@ public class GeomUtil
int x = p1.x + (int)Math.round(1000*Math.cos(theta)), int x = p1.x + (int)Math.round(1000*Math.cos(theta)),
y = p1.y + (int)Math.round(1000*Math.sin(theta)); y = p1.y + (int)Math.round(1000*Math.sin(theta));
// now dot the vector from p1->p2 with the vector from p1->N, if // now dot the vector from p1->p2 with the vector from p1->N, if it's positive, we're on
// it's positive, we're on the right hand side, if it's negative // the right hand side, if it's negative we're on the left hand side and if it's zero,
// we're on the left hand side and if it's zero, we're on the line // we're on the line
return dot(p1.x, p1.y, p2.x, p2.y, x, y); return dot(p1.x, p1.y, p2.x, p2.y, x, y);
} }
/** /**
* Shifts the position of the <code>tainer</code> rectangle to ensure * Shifts the position of the <code>tainer</code> rectangle to ensure that it contains the
* that it contains the <code>tained</code> rectangle. The * <code>tained</code> rectangle. The <code>tainer</code> rectangle must be larger than or
* <code>tainer</code> rectangle must be larger than or equal to the * equal to the size of the <code>tained</code> rectangle.
* size of the <code>tained</code> rectangle.
*/ */
public static void shiftToContain (Rectangle tainer, Rectangle tained) public static void shiftToContain (Rectangle tainer, Rectangle tained)
{ {
@@ -206,17 +192,15 @@ public class GeomUtil
} }
/** /**
* Adds the target rectangle to the bounds of the source rectangle. If * Adds the target rectangle to the bounds of the source rectangle. If the source rectangle is
* the source rectangle is null, a new rectangle is created that is the * null, a new rectangle is created that is the size of the target rectangle.
* size of the target rectangle.
* *
* @return the source rectangle. * @return the source rectangle.
*/ */
public static Rectangle grow (Rectangle source, Rectangle target) public static Rectangle grow (Rectangle source, Rectangle target)
{ {
if (target == null) { if (target == null) {
Log.warning("Can't grow with null rectangle [src=" + source + Log.warning("Can't grow with null rectangle [src=" + source + ", tgt=" + target + "].");
", tgt=" + target + "].");
Thread.dumpStack(); Thread.dumpStack();
} else if (source == null) { } else if (source == null) {
source = new Rectangle(target); source = new Rectangle(target);
@@ -227,25 +211,36 @@ public class GeomUtil
} }
/** /**
* Returns the rectangle containing the specified tile in the supplied * Returns the rectangle containing the specified tile in the supplied larger rectangle. Tiles
* larger rectangle. Tiles go from left to right, top to bottom. * go from left to right, top to bottom.
*/ */
public static Rectangle getTile ( public static Rectangle getTile (
int width, int height, int tileWidth, int tileHeight, int tileIndex) int width, int height, int tileWidth, int tileHeight, int tileIndex)
{
Rectangle bounds = new Rectangle();
getTile(width, height, tileWidth, tileHeight, tileIndex, bounds);
return bounds;
}
/**
* Fills in the bounds of the specified tile in the supplied larger rectangle. Tiles go from
* left to right, top to bottom.
*/
public static void getTile (int width, int height, int tileWidth, int tileHeight, int tileIndex,
Rectangle bounds)
{ {
// figure out from whence to crop the tile // figure out from whence to crop the tile
int tilesPerRow = width / tileWidth; int tilesPerRow = width / tileWidth;
// if we got a bogus region, return bogus tile bounds // if we got a bogus region, return bogus tile bounds
if (tilesPerRow == 0) { if (tilesPerRow == 0) {
return new Rectangle(0, 0, width, height); bounds.setBounds(0, 0, width, height);
} else {
int row = tileIndex / tilesPerRow;
int col = tileIndex % tilesPerRow;
// crop the tile-sized image chunk from the full image
bounds.setBounds(tileWidth*col, tileHeight*row, tileWidth, tileHeight);
} }
int row = tileIndex / tilesPerRow;
int col = tileIndex % tilesPerRow;
// crop the tile-sized image chunk from the full image
return new Rectangle(
tileWidth*col, tileHeight*row, tileWidth, tileHeight);
} }
} }