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:
@@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user