public class Coord
extends java.lang.Object
implements java.io.Serializable
get(int, int)
, which retrieves an
already-existing Coord from the pool if possible, and always returns a usable Coord.
squidpony.squidgrid
, with squidpony.squidgrid.zone
providing an abstraction around groups of Coord and squidpony.squidgrid.iterator
providing various ways to
iterate through the Coords that make up a larger shape. In this package, squidpony.squidmath
, a few classes
should be pointed out. CoordPacker
is a class with all static methods that provides various ways to compress
the memory usage of regions made of many Coord values (and can be constructed in other ways but still provide Coords
later), but since Coords don't use much memory anyway, the real use of the class is for manipulating the shapes and
sizes of the regions those Coords are part of. GreasedRegion
has similar functionality to CoordPacker, but
where CoordPacker is purely static, taking and returning regions as encoded, usually-low-memory-cost arrays of
short
that it considers immutable, a GreasedRegion is a mutable object that allows the same region-altering
techniques to be applied in-place in a way that is relatively (very) low-time-cost. If deciding between the two,
GreasedRegion should usually be preferred, and CoordPacker cannot actually be used when storing regions in larger
than a 256x256 space (usually when the Coord pool has been expanded; see below); GreasedRegion can store potentially
large positions.
expandPoolTo(int, int)
or
expandPool(int, int)
, which cause more memory to be spent initially on storing Coords but can save memory
or ease GC pressure over the long term by preventing duplicate Coords from being created many times. The pool can
never shrink because allowing that would cause completely unpredictable results if existing Coords were in use, or
could easily cause crashes on Android after resuming an application that had previously shrunken the pool due to
platform quirks. Long story short, you should only expand the pool size when your game needs a larger set of 2D
points it will commonly use, and in most cases you shouldn't need to change it at all.
Created by Tommy Ettinger on 8/12/2015.Modifier and Type | Field and Description |
---|---|
int |
x
The x-coordinate.
|
int |
y
The y-coordinate (the ordinate)
|
Modifier | Constructor and Description |
---|---|
protected |
Coord() |
protected |
Coord(int x,
int y) |
Modifier and Type | Method and Description |
---|---|
Coord |
add(Coord other)
Separately combines the x and y positions of this Coord and other, producing a different Coord as their "sum."
|
Coord |
add(double operand)
Separately adds the x and y positions of this Coord to operand, rounding to the nearest int for each of x
and y and producing a different Coord as their "sum."
|
Coord |
add(int operand)
Separately adds the x and y positions of this Coord to operand, producing a different Coord as their
"sum."
|
Coord |
average(Coord other)
Separately averages the x and y positions of this Coord with other, producing a different Coord as their
"midpoint."
|
static int |
cantorHashCode(int x,
int y)
A static version of an earlier
hashCode() method of this class, taking x and y as parameters instead of
requiring a Coord object. |
static Coord |
decode(int code)
This can take an int produced by
someCoord.encode() and get the original Coord back out of it. |
static double |
degrees(Coord from,
Coord to)
Gets the angle in degrees to go between two Coords.
|
double |
distance(Coord co) |
double |
distance(double x2,
double y2) |
double |
distanceSq(Coord co) |
double |
distanceSq(double x2,
double y2) |
Coord |
divide(Coord other)
Separately divides the x and y positions of this Coord by other, producing a different Coord as their
"quotient." If other has 0 for x or y, this will throw an exception, as dividing by 0 is expected to do.
|
Coord |
divide(double operand)
Separately divides the x and y positions of this Coord by operand, flooring to a lower int for each of x and
y and producing a different Coord as their "quotient." If operand is 0.0, expect strange results (infinity and
NaN are both possibilities).
|
Coord |
divide(int operand)
Separately divides the x and y positions of this Coord by operand, producing a different Coord as their
"quotient." If operand is 0, this will throw an exception, as dividing by 0 is expected to do.
|
Coord |
divideRounding(double operand)
Separately divides the x and y positions of this Coord by operand, rounding to the nearest int for each of x and
y and producing a different Coord as their "quotient." If operand is 0.0, expect strange results (infinity and
NaN are both possibilities).
|
int |
encode()
Something like hashCode(), but reversible with
Coord.decode() . |
boolean |
equals(java.lang.Object o) |
static void |
expandPool(int xIncrease,
int yIncrease)
Enlarges the pool of cached Coords by the given amount of expansion for x and y.
|
static void |
expandPoolTo(int width,
int height)
Enlarges the pool of cached Coords to the given width and height, and doesn't change
a dimension if it would be reduced in size.
|
static Coord |
get(int x,
int y) |
static int |
getCacheHeight()
Gets the height of the pool used as a cache for Coords, not including negative Coords.
|
static int |
getCacheWidth()
Gets the width of the pool used as a cache for Coords, not including negative Coords.
|
Coord |
getLocation()
Provided for compatibility with earlier code that used the AWT Point API.
|
int |
getX() |
int |
getY() |
int |
hashCode()
Gets the hash code for this Coord; does not use the standard "auto-complete" style of hash that most IDEs will
generate, but instead uses a highly-specific technique based on the Rosenberg-Strong pairing function, a Gray
code, and two XLCG steps at the end.
|
Coord |
interpolate(Coord end,
float amountTraveled)
Gets a (usually cached) Coord between this Coord and
end , with the actual position relative to this based
on amountTraveled . |
boolean |
isAdjacent(Coord c) |
boolean |
isWithin(int width,
int height)
Returns true if x is between 0 (inclusive) and width (exclusive) and y is between 0 (inclusive) and height
(exclusive), false otherwise.
|
boolean |
isWithinRectangle(int minX,
int minY,
int maxX,
int maxY)
Returns true if x is between minX (inclusive) and maxX (exclusive) and y is between minY (inclusive) and maxY
(exclusive), false otherwise.
|
Coord |
makeEven()
Gets a Coord based off this instance but with odd values for x and/or y decreased to the nearest even number.
|
Coord |
makeOdd()
Gets a Coord based off this instance but with even values for x and/or y increased to the nearest odd number.
|
Coord |
multiply(Coord other)
Separately multiplies the x and y positions of other from this Coord, producing a different Coord as their
"product."
|
Coord |
multiply(double operand)
Separately multiplies the x and y positions of this Coord by operand, rounding to the nearest int for each of x
and y and producing a different Coord as their "product."
|
Coord |
multiply(int operand)
Separately multiplies the x and y positions of this Coord by operand, producing a different Coord as their
"product."
|
static int |
pureEncode(int x,
int y)
An alternative to getting a Coord with Coord.get() only to encode() it as the next step.
|
static int |
rosenbergStrongHashCode(int x,
int y)
A static version of the current
hashCode() method of this class, taking x and y as parameters instead of
requiring a Coord object. |
Coord |
scale(int i) |
Coord |
scale(int i,
int j) |
Coord |
setX(int x) |
Coord |
setY(int y) |
Coord |
subtract(Coord other)
Separately subtracts the x and y positions of other from this Coord, producing a different Coord as their
"difference."
|
Coord |
subtract(double operand)
Separately subtracts operand from the x and y positions of this Coord, rounding to the nearest int for each of x
and y and producing a different Coord as their "difference."
|
Coord |
subtract(int operand)
Separately subtracts operand from the x and y positions of this Coord, producing a different Coord as their
"difference."
|
Direction |
toGoTo(Coord target)
Gets the
Direction needed to get to target from this; typically this is more useful when target
and this are adjacent (by isAdjacent(Coord) ) since that should make it possible to go to target. |
java.lang.String |
toString() |
Coord |
translate(Direction d) |
Coord |
translate(int x,
int y)
Takes this Coord, adds x to its x and y to its y, and returns the Coord at that position.
|
Coord |
translateCapped(int x,
int y,
int width,
int height)
Takes this Coord, adds x to its x and y to its y, limiting x from 0 to width and limiting y from 0 to height,
and returns the Coord at that position.
|
static int |
xoroHashCode(int x,
int y)
An earlier hashCode() implementation used by this class, now standalone in case you want to replicate the results
of the older code.
|
public final int x
public final int y
public static Coord get(int x, int y)
public static double degrees(Coord from, Coord to)
to.x
is greater than from.x
, this returns 0.
When only y is different and to.y
is greater than from.y
, this returns 90.
When only x is different and to.x
is less than from.x
, this returns 180.
When only y is different and to.y
is less than from.y
, this returns 270.
In cases between these, the angle is between those values; it cannot be 360 but it can be very close. This never
returns a negative angle. Keep in mind, "up" depends on how your code orients the y-axis, and SquidLib generally
defaults to positive y going toward the bottom of the screen, like how later lines in a paragraph are further
down on the page.
to.y
was greater than from.y
and x was equal. Because that typically runs
counter to expectations from actual math, the behavior was changed.from
- the starting Coord to measure fromto
- the ending Coord to measure tofrom
to to
; 0 is uppublic Coord getLocation()
public Coord translate(int x, int y)
x
- the amount of x distance to movey
- the amount of y distance to movepublic Coord translateCapped(int x, int y, int width, int height)
x
- the amount of x distance to movey
- the amount of y distance to movewidth
- one higher than the maximum x value this can use; typically the length of an arrayheight
- one higher than the maximum y value this can use; typically the length of an arraypublic Coord add(Coord other)
other
- another Coordx = this.x + other.x; y = this.y + other.y
public Coord add(int operand)
operand
- a value to add each of x and y tox = this.x + operand; y = this.y + operand
public Coord add(double operand)
operand
- a value to add each of x and y tox = this.x + operand; y = this.y +
operand
, with both x and y rounded accordinglypublic Coord subtract(Coord other)
other
- another Coordx = this.x - other.x; y = this.y - other.y
public Coord subtract(int operand)
operand
- a value to subtract from each of x and yx = this.x - operand; y = this.y - operand
public Coord subtract(double operand)
operand
- a value to subtract from each of x and yx = this.x - operand; y = this.y -
operand
, with both x and y rounded accordinglypublic Coord multiply(Coord other)
other
- another Coordx = this.x * other.x; y = this.y * other.y
public Coord multiply(int operand)
operand
- a value to multiply each of x and y byx = this.x * operand; y = this.y * operand
public Coord multiply(double operand)
operand
- a value to multiply each of x and y byx = this.x * operand; y = this.y *
operand
, with both x and y rounded accordinglypublic Coord divide(Coord other)
other
- another Coordx = this.x / other.x; y = this.y / other.y
public Coord divide(int operand)
operand
- a value to divide each of x and y byx = this.x / operand; y = this.y / operand
public Coord divide(double operand)
operand
- a value to divide each of x and y byx = this.x / operand; y = this.y /
operand
, with both x and y rounded accordinglypublic Coord divideRounding(double operand)
operand
- a value to divide each of x and y byx = this.x / operand; y = this.y /
operand
, with both x and y rounded accordinglypublic Coord average(Coord other)
other
- another Coordpublic Coord translate(Direction d)
d
- A non-null
direction.d
on this
.public Coord scale(int i)
i
- (x*i,y*i)
.public Coord scale(int i, int j)
i
- (x*i,y*j)
.public double distance(double x2, double y2)
public double distance(Coord co)
public double distanceSq(double x2, double y2)
public double distanceSq(Coord co)
public Coord makeEven()
ThinDungeonGenerator
and used
with Adjacency.ThinWallAdjacency
.public Coord makeOdd()
ThinDungeonGenerator
and used
with Adjacency.ThinWallAdjacency
.public boolean isAdjacent(Coord c)
c
- this
is adjacent to c
. Not that a cell is
not adjacent to itself with this method.public Direction toGoTo(Coord target)
Direction
needed to get to target
from this; typically this is more useful when target
and this are adjacent (by isAdjacent(Coord)
) since that should make it possible to go to target.
Direction.toGoTo(Coord, Coord)
, and some code may prefer using the method
in Direction instead of this one. Earlier versions of this code only worked for adjacent Coords, which seemed
like an unnecessary limitation since Direction's version worked for any arguments.target
- a non-null Coord
this
to target
public boolean isWithin(int width, int height)
width
- the upper limit on x to check, exclusiveheight
- the upper limit on y to check, exclusivepublic boolean isWithinRectangle(int minX, int minY, int maxX, int maxY)
minX
- the lower limit on x to check, inclusiveminY
- the lower limit on y to check, inclusivemaxX
- the upper limit on x to check, exclusivemaxY
- the upper limit on y to check, exclusivepublic int getX()
public Coord setX(int x)
public int getY()
public Coord setY(int y)
public java.lang.String toString()
toString
in class java.lang.Object
public int hashCode()
Objects.hash(Object...)
gives more than a 75% collision rate). The previous version, which is
still available as cantorHashCode(int, int)
, has slightly better results when used for seeding
procedural generation based on a Coord (a reasonable usage of this method), but both this hash code and the
Cantor-based one have excellent randomness in the upper bits of the hash (so if you use a hashCode() result as a
whole int, then it should be pretty good as a seed). The method before the Cantor-based one,
xoroHashCode(int, int)
was structured a little like xoroshiro (XoRoRNG
uses the 64-bit version
of xoroshiro), and while it had pretty low collision rates (low 5% range), its hash codes changed bits in large
checkerboard patterns, leaving heavy square-shaped biases in generated results.
OrderedSet
and OrderedMap
; if you use the ordered kinds, then the only things that matter about
this hash code are that it's fast (it's fast enough), it's cross-platform compatible (this version avoids using
long values, which are slow on GWT, and is carefully written to behave the same on GWT as desktop) and that it
doesn't collide often (which is now much more accurate than in earlier versions of this method).hashCode
in class java.lang.Object
A static method that gets the same result as this method without involving a Coord
public static int cantorHashCode(int x, int y)
hashCode()
method of this class, taking x and y as parameters instead of
requiring a Coord object. Like the earlier hashCode() method, this involves the close-to-optimal mathematical
Cantor pairing function to distribute x and y without overlap until they get very large. Cantor's pairing
function can be written simply as ((x + y) * (x + y + 1)) / 2 + y
; it produces sequential results for a
sequence of positive points traveling in diagonal stripes away from the origin. The finalization steps this
performs improve the randomness of the lower bits, but also worsen collision rates; most cases involving Coords
will see lower collision rates from rosenbergStrongHashCode(int, int)
, but more random results from this
method.x
- the x coordinate of the "imaginary Coord" to hashy
- the y coordinate of the "imaginary Coord" to hashpublic static int rosenbergStrongHashCode(int x, int y)
hashCode()
method of this class, taking x and y as parameters instead of
requiring a Coord object. Like the current hashCode() method, this involves the close-to-optimal mathematical
Rosenberg-Strong pairing function to distribute x and y without overlap until they get very large. The
Rosenberg-Strong pairing function can be written simply as ((x >= y) ? x * (x + 2) - y : y * y + x)
; it
produces sequential results for a sequence of positive points traveling in square "shells" away from the origin.
the algorithm is discussed more here; the only
changes this makes are adding 3 to x and y (to account for the minimum of -3 in most cases for a Coord), and some
finalizing steps that help randomize the upper bits of the hash code (the lower bits are quite non-random because
they can't permit any gaps while optimizing collision rates).x
- the x coordinate of the "imaginary Coord" to hashy
- the y coordinate of the "imaginary Coord" to hashpublic static int xoroHashCode(int x, int y)
XoRoRNG
and Lathe32RNG
in particular, but using only bitwise math.x
- the x coordinate of the "imaginary Coord" to hashy
- the y coordinate of the "imaginary Coord" to hashpublic int encode()
Coord.decode()
. Works for Coords between roughly -256 and
32000 in each of x and y, but will probably only decode to pooled Coords if x and y are both between -3 and 255
(inclusive for both).public static int pureEncode(int x, int y)
x
- the x position to encodey
- the y position to encodepublic static Coord decode(int code)
someCoord.encode()
and get the original Coord back out of it. It
works for all pooled Coords where the pool hasn't been expanded past about 32,000 in either dimension. It even
works for Coords with negative x or y as well, if they are no lower than -256 in either dimension. This will
almost certainly fail (producing a gibberish Coord that probably won't be pooled) on hashes produced by any other
class, including subclasses of Coord.code
- an encoded int from a Coord, but not a subclass of Coordpublic boolean equals(java.lang.Object o)
equals
in class java.lang.Object
public static int getCacheWidth()
public static int getCacheHeight()
public static void expandPoolTo(int width, int height)
width
- the new width for the pool of cached Coords; will be ignored if smaller than the current widthheight
- the new height for the pool of cached Coords; will be ignored if smaller than the current heightpublic static void expandPool(int xIncrease, int yIncrease)
xIncrease
- the amount to increase cache's width byyIncrease
- the amount to increase cache's height bypublic Coord interpolate(Coord end, float amountTraveled)
end
, with the actual position relative to this based
on amountTraveled
. If amountTraveled is 0, this simply returns a Coord equal to this; if amountTraveled
is 1, this returns a Coord equal to end, and values in between 0 and 1 give Coords between this and end.end
- another Coord that acts as the "far" endpoint, where this is the "near" start pointamountTraveled
- a float between 0 and 1 inclusive, with lower meaning closer to this, higher meaning closer to endCopyright © Eben Howard 2012–2022. All rights reserved.