Class Region

java.lang.Object
com.github.yellowstonegames.grid.Region
All Implemented Interfaces:
Iterable<Coord>, Collection<Coord>

public class Region extends Object implements Collection<Coord>
Region encoding of on/off information about areas using bitsets; uncompressed but fast at bulk operations. This can handle any size of 2D data, but it's almost always best for the Coord pool to be at least as large as the max dimensions of a Region (use Coord.expandPoolTo(int, int) to ensure this). It stores several long arrays and uses each bit in one of those numbers to represent a single point, though sometimes this does waste bits if the height of the area this encodes is not a multiple of 64 (if you store a 80x64 map, this uses 80 longs; if you store an 80x65 map, this uses 160 longs, 80 for the first 64 rows and 80 more to store the next row). It's very fast at certain bulk operations (anything that expands or retracts an area, including expand(), retract(), fringe(), surface(), and flood(Region), and maintains the high speed at "bitwise-like" operations that bitsets typically have (for example, on and(Region), or(Region), and xor(Region)).
Each Region is mutable, and instance methods typically modify that instance and return it for chaining. There are exceptions, usually where multiple Region values are returned and the instance is not modified.
Typical usage involves constructing a Region from some input data, like a char[][] for a map or a float[][] from DijkstraMap, and modifying it spatially with expand(), retract(), flood(), etc. It's common to mix in data from other Regions with and() (which gets the intersection of two Regions and stores it in one), or() (which is like and() but for the union), xor() (like and() but for exclusive or, finding only cells that are on in exactly one of the two Regions), and andNot() (which can be considered the "subtract another region from me" method). There are 8-way (Chebyshev distance) variants on all of the spatial methods, and methods without "8way" in the name are either 4-way (Manhattan distance) or not affected by distance measurement. There's really quite a lot of methods here that modify a Region, so here's a partial list:
Once you have a Region, you may want to:
You may also want to produce some 2D data from one or more Regions, as with sum(Region...) or toChars(). The most effective techniques regarding Region involve multiple methods, like getting a few random points from an existing Region representing floor tiles in a dungeon with randomRegion(EnhancedRandom, int), then finding a random expansion of those initial points with spill(Region, int, EnhancedRandom), giving the original Region of floor tiles as the first argument. This could be used to position puddles of water or toxic waste in a dungeon level, while still keeping the starting points and finished points within the boundaries of valid (floor) cells. If you wanted to place something like mold that can be on floors or on cells immediately adjacent to floors (like walls), you could call expand() on the floor tiles before calling spill, allowing the spill to spread onto non-floor cells that are next to floors.
For efficiency, you can place one Region into another (typically a temporary value that is no longer needed and can be recycled) using remake(Region), or give the information that would normally be used to construct a fresh Region to an existing one of the same dimensions with refill(boolean[][]) or any of the overloads of refill(). These re-methods don't do as much work as a constructor does if the width and height of their argument are identical to their current width and height, and don't create more garbage for the GC.
  • Nested Class Summary

    Nested Classes
    Modifier and Type
    Class
    Description
    class 
     
  • Field Summary

    Fields
    Modifier and Type
    Field
    Description
    static final Region[]
    A 256-element array of Regions, each 64x64, where the first Region has an impossibly strict threshold on what points to include (it is empty), but the second has some points far apart, the third has more, and so on until the last element includes almost all points.
    long[]
     
    int
     
    int
     
  • Constructor Summary

    Constructors
    Constructor
    Description
    Constructs an empty 4x64 Region.
    Region(boolean[][] bits)
    Constructs a Region with the given rectangular boolean array, with width of bits.length and height of bits[0].length, any value of true considered "on", and any value of false considered "off."
    Region(boolean[] bits, int width, int height)
    Constructs a Region with the given 1D boolean array, with the given width and height, where an [x][y] position is obtained from bits given an index n with x = n / height, y = n % height, any value of true considered "on", and any value of false considered "off."
    Region(byte[][] map, int lower, int upper)
    Constructs this Region using a byte[][], treating cells as on if they are greater than or equal to lower and less than upper, or off otherwise.
    Region(char[][] map, char yes)
    Constructs a Region with the given rectangular char array, with width of map.length and height of map[0].length, any value that equals yes is considered "on", and any other value considered "off."
    Region(char[][] map, char[] yes)
    Constructs a Region with the given rectangular char array, with width of map.length and height of map[0].length, any value that equals yes is considered "on", and any other value considered "off."
    Region(float[][] map, float upperBound)
    Constructs this Region using a float[][] (typically one generated by DijkstraMap) that only stores two relevant states: an "on" state for values less than or equal to upperBound (inclusive), and an "off" state for anything else.
    Region(float[][] map, float lowerBound, float upperBound)
    Constructs this Region using a float[][] (typically one generated by DijkstraMap) that only stores two relevant states: an "on" state for values between lowerBound (inclusive) and upperBound (exclusive), and an "off" state for anything else.
    Region(float[][] map, float lowerBound, float upperBound, int scale)
    Constructs this Region using a float[][] that only stores two relevant states: an "on" state for values between lowerBound (inclusive) and upperBound (exclusive), and an "off" state for anything else.
    Region(int[][] map, int yes)
    Constructs a Region with the given rectangular int array, with width of map.length and height of map[0].length, any value that equals yes is considered "on", and any other value considered "off."
    Region(int[][] map, int lower, int upper)
    Constructs this Region using an int[][], treating cells as on if they are greater than or equal to lower and less than upper, or off otherwise.
    Region(int width, int height)
    Constructor for an empty Region of the given width and height.
    Region(int width, int height, Coord... points)
    Constructor for a Region that can have several "on" cells specified, and has the given width and height.
    Region(int width, int height, Iterable<Coord> points)
    Constructor for a Region that can have several "on" cells specified, and has the given width and height.
    Region(long[] data2, int width, int height)
    Primarily for internal use, this constructor copies data2 exactly into the internal long array the new Region will use, and does not perform any validation steps to ensure that cells that would be "on" but are outside the actual height of the Region are actually removed (this only matters if height is not a multiple of 64).
    Region(long[] data2, int dataWidth, int dataHeight, int width, int height)
    Primarily for internal use, this constructor copies data2 into the internal long array the new Region will use, but treats data2 as having the dimensions [dataWidth][dataHeight], and uses the potentially-different dimensions [width][height] for the constructed Region.
    Region(short[][] map, int lower, int upper)
    Constructs this Region using a short[][], treating cells as on if they are greater than or equal to lower and less than upper, or off otherwise.
    Region(com.github.tommyettinger.function.IntIntPredicate decider, int width, int height)
    Constructs a Region with the given width and height by calling decider's functional method on each x,y position for x from 0 (inclusive) to width (exclusive) and for y from 0 (inclusive) to height (exclusive).
    Region(com.github.tommyettinger.random.EnhancedRandom random, float fraction, int width, int height)
    Constructor for a random Region of the given width and height, trying to set the given fraction of cells to on.
    Region(com.github.tommyettinger.random.EnhancedRandom random, int width, int height)
    Constructor for a random Region of the given width and height, typically assigning approximately half of the cells in this to "on" and the rest to off.
    Region(Coord single, int width, int height)
    Constructor for a Region that contains a single "on" cell, and has the given width and height.
    Region(INoise noise, float lower, float upper, int width, int height)
    Constructs a Region with the given width and height by calling INoise.getNoise(float, float) position for x from 0 (inclusive) to width (exclusive) and for y from 0 (inclusive) to height (exclusive).
    Region(Region other)
    Copy constructor that takes another Region and copies all of its data into this new one.
    Region(String[] map, char yes)
    Weird constructor that takes a String array, _as it would be printed_, so each String is a row and indexing would be done with y, x instead of the normal x, y.
  • Method Summary

    Modifier and Type
    Method
    Description
    boolean
    add(Coord coord)
     
    boolean
    addAll(Collection<? extends Coord> c)
     
    Sets all cells in this to "on."
    alterBounds(int widthChange, int heightChange)
    Changes the width and/or height of this Region, enlarging or shrinking starting at the edges where x == width - 1 and y == height - 1.
    and(Region other)
    Intersection of two Regions, assigning the result into this Region.
    andNot(Region other)
    Difference of two Regions, assigning the result into this Region.
    Intersection of two Regions, assigning the result into this Region, with the special requirement that other must be a 64x64 area, and the special property that other will be considered tiled to cover all of the area of this Region.
    appendContaining(Collection<Region> into, int x, int y, Region... packed)
    Tries to look up the position x,y in each Region in packed; each Region that contains that x,y point is appended into the Collection into.
    appendContaining(Collection<Region> into, int x, int y, Collection<Region> packed)
    Tries to look up the position x,y in each Region in packed; each Region that contains that x,y point is appended into the Collection into.
    static long
    approximateBits(com.github.tommyettinger.random.EnhancedRandom random, int bitCount)
    Generates a random 64-bit long with a number of '1' bits (Hamming weight) equal on average to bitCount.
     
    asCoords(Coord[] points)
     
    int[]
     
    int[]
     
    atFraction(float fraction)
     
    int
    atFractionTight(float fraction)
     
    static int[][]
    bitSum(Region... regions)
    Generates a 2D int array from an array or vararg of Regions, treating each cell in the nth region as the nth bit of the int at the corresponding x,y cell in the int array.
    void
     
    Takes the pairs of "on" cells in this Region that are separated by exactly one cell in an orthogonal line, and changes the gap cells to "on" as well.
    Takes the pairs of "on" cells in this Region that are separated by exactly one cell in an orthogonal or diagonal line, and changes the gap cells to "on" as well.
    Takes the pairs of "on" cells in this Region that are separated by exactly one cell in an orthogonal or diagonal line, and changes the gap cells to "on" as well.
    Takes the pairs of "on" cells in this Region that are separated by exactly one cell in an orthogonal or diagonal line, and changes the gap cells to "on" as well.
    boolean
    contains(int x, int y)
     
    boolean
    Checks if c is present in this Region.
    boolean
     
    boolean
     
    Simple method that returns a newly-allocated copy of this Region; modifications to one won't change the other, and this method returns the copy while leaving the original unchanged.
    copyRotated(int turns)
    Makes a copy of this Region that has been rotated 90 degrees turns times.
    boolean[][]
    Returns this Region's data as a 2D boolean array, [width][height] in size, with on treated as true and off treated as false.
    static Region
    decompress(String compressed)
    Decompresses a String returned by toCompressedString(), returning a new Region with identical width, height, and contents to the Region before compression.
    decompressInto(String compressed)
    Decompresses a String returned by toCompressedString(), and assigns into this region the width, height, and contents of the data before compression.
    deteriorate(com.github.tommyettinger.random.EnhancedRandom random, float preservation)
    Randomly removes points from a Region, with preservation as a fraction between 1.0 (keep all) and 0.0 (remove all).
    deteriorate(com.github.tommyettinger.random.EnhancedRandom rng, int preservation)
    Randomly removes points from a Region, with larger values for preservation keeping more of the existing shape intact.
    int[][]
    dijkstraScan(int[][] into, Coord goal)
    A crude approximation of DijkstraMap's scan() method for when DijkstraMap isn't available.
    int[][]
    dijkstraScan(int[][] into, Coord goal, int limit)
    A crude approximation of DijkstraMap's scan() method for when DijkstraMap isn't available.
    int[][]
    dijkstraScan(int[][] into, Region goals)
    A crude approximation of DijkstraMap's scan() method for when DijkstraMap isn't available.
    int[][]
    dijkstraScan(int[][] into, Region goals, int limit)
    A crude approximation of DijkstraMap's scan() method for when DijkstraMap isn't available.
    Removes "on" cells that are orthogonally adjacent to other "on" cells, keeping at least one cell in a group "on." Uses a "checkerboard" pattern to determine which cells to turn off, with all cells that would be black on a checkerboard turned off and all others kept as-is.
    Removes "on" cells that are 8-way adjacent to other "on" cells, keeping at least one cell in a group "on." Uses a "grid-like" pattern to determine which cells to turn off, with all cells with even x and even y kept as-is but all other cells (with either or both odd x or odd y) turned off.
    static int
    disperseBits(int n)
    Narrow-purpose; takes an int that represents a distance down the Z-order curve and moves its bits around so that its x component is stored in the bottom 16 bits (use (n & 0xffff) to obtain) and its y component is stored in the upper 16 bits (use (n >>> 16) to obtain).
    disperseRandom(com.github.tommyettinger.random.EnhancedRandom random)
    Removes "on" cells that are nearby other "on" cells, with a random factor to which bits are actually turned off that still ensures exactly half of the bits are kept as-is (the one exception is when height is an odd number, which makes the bottom row slightly random).
    Equivalent to clear(), setting all cells to "off," but also returns this for chaining.
    boolean
     
    Takes the "on" cells in this Region and expands them by one cell in the 4 orthogonal directions, making each "on" cell take up a plus-shaped area that may overlap with other "on" cells (which is just a normal "on" cell then).
    expand(int amount)
    Takes the "on" cells in this Region and expands them by amount cells in the 4 orthogonal directions, making each "on" cell take up a plus-shaped area that may overlap with other "on" cells (which is just a normal "on" cell then).
    expand(int amount, Region temp)
    Takes the "on" cells in this Region and expands them by amount cells in the 4 orthogonal directions, making each "on" cell take up a plus-shaped area that may overlap with other "on" cells (which is just a normal "on" cell then).
    expand(Region temp)
    Takes the "on" cells in this Region and expands them by one cell in the 4 orthogonal directions, making each "on" cell take up a plus-shaped area that may overlap with other "on" cells (which is just a normal "on" cell then).
    Takes the "on" cells in this Region and expands them by one cell in the 8 orthogonal and diagonal directions, making each "on" cell take up a 3x3 square-shaped area that may overlap with other "on" cells (which is just a normal "on" cell then).
    expand8way(int amount)
    Takes the "on" cells in this Region and expands them by amount cells in the 8 orthogonal and diagonal directions, making each "on" cell take up a square-shaped area that may overlap with other "on" cells (which is just a normal "on" cell then).
    expand8way(int amount, Region temp)
    Takes the "on" cells in this Region and expands them by amount cells in the 8 orthogonal and diagonal directions, making each "on" cell take up a square-shaped area that may overlap with other "on" cells (which is just a normal "on" cell then).
    Takes the "on" cells in this Region and expands them by one cell in the 8 orthogonal and diagonal directions, making each "on" cell take up a 3x3 square-shaped area that may overlap with other "on" cells (which is just a normal "on" cell then).
    expandSeries(int amount)
    Takes the "on" cells in this Region and produces amount Regions, each one expanded by 1 cell in the 4 orthogonal directions relative to the previous Region, making each "on" cell take up a plus-shaped area that may overlap with other "on" cells (which is just a normal "on" cell then).
    expandSeries8way(int amount)
    Takes the "on" cells in this Region and produces amount Regions, each one expanded by 1 cell in the 8 orthogonal and diagonal directions relative to the previous Region, making each "on" cell take up a square-shaped area that may overlap with other "on" cells (which is just a normal "on" cell then).
    com.github.tommyettinger.ds.ObjectList<Region>
    Returns a new ObjectList of Region where each item is a progressively more and more expand()-ed copy of this Region, until ending where the entire Region is "on" cells.
    com.github.tommyettinger.ds.ObjectList<Region>
    Returns a new ObjectList of Region where each item is a progressively more and more expand8way()-ed copy of this Region, until just before the entire Region is "on" cells.
    fill(boolean contents)
    Sets all cells in this to "on" if contents is true, or "off" if contents is false.
    Gets the first Coord in the iteration order, or (-1,-1) if this Region is empty.
    int
     
    fit(float xFraction, float yFraction)
     
    int[][]
    fit(int[][] basis, int defaultValue)
     
    flip(boolean leftRight, boolean upDown)
     
    flood(Region bounds)
    Like expand(), but limits expansion to the "on" cells of bounds.
    flood(Region bounds, int amount)
    Like expand(int), but limits expansion to the "on" cells of bounds.
    flood(Region bounds, int amount, Region buffer)
    Like expand(int), but limits expansion to the "on" cells of bounds.
    flood(Region bounds, Region buffer)
    Like expand(), but limits expansion to the "on" cells of bounds.
    flood8way(Region bounds)
    Like expand8way(), but limits expansion to the "on" cells of bounds.
    flood8way(Region bounds, int amount)
    Like expand8way(int), but limits expansion to the "on" cells of bounds.
    flood8way(Region bounds, int amount, Region buffer)
    Like expand8way(int), but limits expansion to the "on" cells of bounds.
    flood8way(Region bounds, Region buffer)
    Like expand8way(), but limits expansion to the "on" cells of bounds.
    floodSeries(Region bounds, int amount)
    Repeatedly calls flood(Region) amount times and returns the intermediate steps in a Region array of size amount.
    floodSeries8way(Region bounds, int amount)
    Repeatedly calls flood8way(Region) amount times and returns the intermediate steps in a Region array of size amount.
    com.github.tommyettinger.ds.ObjectList<Region>
    Repeatedly generates new Regions, each one cell expanded in 4 directions from the previous Region and staying inside the "on" cells of bounds, until it can't expand any more.
    com.github.tommyettinger.ds.ObjectList<Region>
    Repeatedly generates new Regions, each one cell expanded in 8 directions from the previous Region and staying inside the "on" cells of bounds, until it can't expand anymore.
    fray(float fractionKept)
    Like retract(), this removes the "on" cells that are 4-way-adjacent to any "off" cell, but unlike that method it keeps a fraction of those surface cells, quasi-randomly selecting them.
    fray(float fractionKept, Region buffer)
    Like retract(), this removes the "on" cells that are 4-way-adjacent to any "off" cell, but unlike that method it keeps a fraction of those surface cells, quasi-randomly selecting them.
    fray(com.github.tommyettinger.random.EnhancedRandom random, float fractionKept)
    Like retract(), this removes the "on" cells that are 4-way-adjacent to any "off" cell, but unlike that method it keeps a fraction of those surface cells, randomly selecting them.
    fray(com.github.tommyettinger.random.EnhancedRandom random, float fractionKept, Region buffer)
    Like retract(), this removes the "on" cells that are 4-way-adjacent to any "off" cell, but unlike that method it keeps a fraction of those surface cells, randomly selecting them.
    Takes the "on" cells in this Region and expands them by one cell in the 4 orthogonal directions, producing a diamond shape, then removes the original area before expansion, producing only the cells that were "off" in this and within 1 cell (orthogonal-only) of an "on" cell.
    fringe(int amount)
    Takes the "on" cells in this Region and expands them by amount cells in the 4 orthogonal directions (iteratively, producing a diamond shape), then removes the original area before expansion, producing only the cells that were "off" in this and within amount cells (orthogonal-only) of an "on" cell.
    fringe(int amount, Region temp, Region temp2)
    Takes the "on" cells in this Region and expands them by amount cells in the 4 orthogonal directions (iteratively, producing a diamond shape), then removes the original area before expansion, producing only the cells that were "off" in this and within amount cells (orthogonal-only) of an "on" cell.
    fringe(Region temp)
    Takes the "on" cells in this Region and expands them by one cell in the 4 orthogonal directions, producing a diamond shape, then removes the original area before expansion, producing only the cells that were "off" in this and within 1 cell (orthogonal-only) of an "on" cell.
    Takes the "on" cells in this Region and expands them by one cell in the 8 orthogonal and diagonal directions, producing a square shape, then removes the original area before expansion, producing only the cells that were "off" in this and within 1 cell (8-way) of an "on" cell.
    fringe8way(int amount)
    Takes the "on" cells in this Region and expands them by amount cells in the 8 orthogonal and diagonal directions (iteratively, producing a square shape), then removes the original area before expansion, producing only the cells that were "off" in this and within amount cells (8-way) of an "on" cell.
    fringe8way(int amount, Region temp, Region temp2)
    Takes the "on" cells in this Region and expands them by amount cells in the 8 orthogonal and diagonal directions (iteratively, producing a square shape), then removes the original area before expansion, producing only the cells that were "off" in this and within amount cells (8-way) of an "on" cell.
    Takes the "on" cells in this Region and expands them by one cell in the 8 orthogonal and diagonal directions, producing a square shape, then removes the original area before expansion, producing only the cells that were "off" in this and within 1 cell (8-way) of an "on" cell.
    fringeSeries(int amount)
    Takes the "on" cells in this Region and produces amount Regions, each one expanded by 1 cell in the 4 orthogonal directions relative to the previous Region, making each "on" cell take up a diamond-shaped area.
    fringeSeries8way(int amount)
    Takes the "on" cells in this Region and produces amount Regions, each one expanded by 1 cell in the 8 orthogonal and diagonal directions relative to the previous Region, making each "on" cell take up a square-shaped area.
    com.github.tommyettinger.ds.ObjectList<Region>
    Returns an ObjectList of progressively further-expanded copied fringes of this Region.
    com.github.tommyettinger.ds.ObjectList<Region>
    Returns an ObjectList of progressively further-expanded copied fringes of this Region.
    long
     
    long
    hash64(long seed)
    Computes a 64-bit hash code of this Region given a 64-bit seed; even if given two very similar seeds, this should produce very different hash codes for the same Region.
    int
     
    insert(int tight)
    Sets the given cell, "tightly" encoded for a specific width/height as by asTightEncoded(), to "on".
    insert(int x, int y)
    Sets the cell at x,y to "on".
    insert(int x, int y, Region other)
    Takes another Region, called other, with potentially different size and inserts its "on" cells into this Region at the given x,y offset, allowing negative x and/or y to put only part of other in this.
    insert(int x, int y, Region other, Region buffer)
    Takes another Region, called other, with potentially different size and inserts its "on" cells into this Region at the given x,y offset, allowing negative x and/or y to put only part of other in this.
    insert(Coord point)
    Sets the cell at point to "on".
    insertCircle(Coord center, int radius)
     
    insertRectangle(int startX, int startY, int rectangleWidth, int rectangleHeight)
     
    insertSeveral(int[] points)
     
    insertSeveral(Coord... points)
     
     
    insertTranslation(int x, int y)
    Adds to this Region with a moved set of its own "on" cells, moved to the given x and y offset.
    insertTranslation(int x, int y, Region buffer)
    Adds to this Region with a moved set of its own "on" cells, moved to the given x and y offset.
    static int
    interleaveBits(int x, int y)
    Narrow-purpose; takes an x and a y value, each between 0 and 65535 inclusive, and interleaves their bits so the least significant bit and every other bit after it are filled with the bits of x, while the second-least-significant bit and every other bit after that are filled with the bits of y.
    boolean
    Returns true if any cell is "on" in both this Region and in other; returns false otherwise.
    char[][]
    intoChars(char[][] chars, char on)
    Fills this Region's data into the given 2D char array, modifying it and returning it, with "on" cells filled with the char parameter on and "off" cells left as-is.
    char[][]
    intoChars(char[][] chars, char on, char off)
    Fills this Region's data into the given 2D char array, modifying it and returning it, with "on" cells filled with the char parameter on and "off" cells with the parameter off.
    boolean
     
     
    Finds the largest contiguous area of "on" cells in this Region and returns it; does not modify this Region.
    Finds the largest contiguous area of "on" cells in this Region and returns it; does not modify this Region.
    Gets the last Coord in the iteration order, or (-1,-1) if this Region is empty.
    int
     
    Returns a new Region that has been mirrored along the rightmost edge, parallel to the y-axis.
    Modifies this Region so the only cells that will be "on" have a neighbor downwards when this is called.
    Modifies this Region so the only cells that will be "on" have a neighbor downwards and to the left when this is called.
    Modifies this Region so the only cells that will be "on" have a neighbor downwards and to the right when this is called.
    Modifies this Region so the only cells that will be "on" have a neighbor to the left when this is called.
    Modifies this Region so the only cells that will be "on" have a neighbor to the right when this is called.
    Modifies this Region so the only cells that will be "on" have a neighbor upwards when this is called.
    Modifies this Region so the only cells that will be "on" have a neighbor upwards and to the left when this is called.
    Modifies this Region so the only cells that will be "on" have a neighbor upwards and to the right when this is called.
    not()
    Negates this Region, turning "on" to "off" and "off" to "on."
    notAnd(Region other)
    Like andNot, but subtracts this Region from other and stores the result in this Region, without mutating other.
    nth(int index)
     
    static Region
    of(int width, int height, long... data)
    Constructs a Region using a vararg for data.
    or(Region other)
    Union of two Regions, assigning the result into this Region.
    void
    perceptualHashQuick(long[] into, int[] working)
    Calculates a perceptual hash for this Region using a method that is only precise for some sizes of Region; it writes a result to into, and uses working as a temporary buffer.
    static long
    randomInterleave(com.github.tommyettinger.random.EnhancedRandom random)
    Gets a somewhat-random long with exactly 32 bits set; in each pair of bits starting at bit 0 and bit 1, then bit 2 and bit 3, up to bit 62 and bit 3, one bit will be 1 and one bit will be 0 in each pair.
    randomPortion(com.github.tommyettinger.random.EnhancedRandom rng, int size)
     
    randomRegion(com.github.tommyettinger.random.EnhancedRandom rng, int size)
     
    randomScatter(com.github.tommyettinger.random.EnhancedRandom rng, int minimumDistance)
    Modifies this Region so it contains a random subset of its previous contents, choosing cells so that the distance between any two "on" cells is at least minimumDistance, with at least one cell as "on" if any were "on" in this originally.
    randomScatter(com.github.tommyettinger.random.EnhancedRandom rng, int minimumDistance, int limit)
    Modifies this Region so it contains a random subset of its previous contents, choosing cells so that the distance between any two "on" cells is at least minimumDistance, with at least one cell as "on" if any were "on" in this originally.
    float
     
    float
     
    refill(boolean[][] map)
    Reassigns this Region with the given rectangular boolean array, reusing the current data storage (without extra allocations) if this.width == map.length and this.height == map[0].length.
    refill(boolean[] bits, int width, int height)
    Reassigns this Region with the given 1D boolean array, reusing the current data storage (without extra allocations) if this.width == width and this.height == height, where an [x][y] position is obtained from bits given an index n with x = n / height, y = n % height, any value of true considered "on", and any value of false considered "off."
    refill(byte[][] map, int lower, int upper)
    Reassigns this Region with the given rectangular byte array, reusing the current data storage (without extra allocations) if this.width == map.length and this.height == map[0].length.
    refill(char[][] map, char yes)
    Reassigns this Region with the given rectangular char array, reusing the current data storage (without extra allocations) if this.width == map.length and this.height == map[0].length.
    refill(char[][] map, char[] yes)
    Reassigns this Region with the given rectangular char array, reusing the current data storage (without extra allocations) if this.width == map.length and this.height == map[0].length.
    refill(float[][] map, float upperBound)
    Reassigns this Region with the given rectangular float array, reusing the current data storage (without extra allocations) if this.width == map.length and this.height == map[0].length.
    refill(float[][] map, float lower, float upper)
    Reassigns this Region with the given rectangular float array, reusing the current data storage (without extra allocations) if this.width == map.length and this.height == map[0].length.
    refill(float[][] map, float lowerBound, float upperBound, int scale)
    Reassigns this Region with the given rectangular float array, reusing the current data storage (without extra allocations) if this.width == map.length * scale && this.height == map[0].length * scale.
    refill(int[][] map, int yes)
    Reassigns this Region with the given rectangular int array, reusing the current data storage (without extra allocations) if this.width == map.length and this.height == map[0].length.
    refill(int[][] map, int lower, int upper)
    Reassigns this Region with the given rectangular int array, reusing the current data storage (without extra allocations) if this.width == map.length and this.height == map[0].length.
    refill(long[] data2, int dataWidth, int dataHeight, int width, int height)
    Primarily for internal use, this method copies data2 into the internal long array the new Region will use, but treats data2 as having the dimensions [dataWidth][dataHeight], and uses the potentially-different dimensions [width][height] for this Region, potentially re-allocating the internal data this uses if width and/or height are different from what they were.
    refill(short[][] map, int lower, int upper)
    Reassigns this Region with the given rectangular short array, reusing the current data storage (without extra allocations) if this.width == map.length and this.height == map[0].length.
    refill(com.github.tommyettinger.function.IntIntPredicate decider, int width, int height)
    Reassigns this Region with the given function to decide which positions will be "on", reusing the current data storage (without extra allocations) if this.width == width and this.height == height.
    refill(com.github.tommyettinger.random.EnhancedRandom random, float fraction, int width, int height)
    Reassigns this Region randomly, reusing the current data storage (without extra allocations) if this.width == width and this.height == height, while trying to set the given fraction of cells to on.
    refill(com.github.tommyettinger.random.EnhancedRandom random, int width, int height)
    Reassigns this Region by filling it with random values from random, reusing the current data storage (without extra allocations) if this.width == width and this.height == height, and typically assigning approximately half of the cells in this to "on" and the rest to off.
    refill(INoise noise, float lower, float upper, int width, int height)
    Reassigns this Region with the given function to decide which positions will be "on", reusing the current data storage (without extra allocations) if this.width == width and this.height == height.
    refill(String[] map, char yes)
    Weird refill method that takes a String array, _as it would be printed_, so each String is a row and indexing would be done with y, x instead of the normal x, y.
    remake(Region other)
    A useful method for efficiency, remake() reassigns this Region to have its contents replaced by other.
    remove(int x, int y)
     
    remove(int x, int y, Region other)
    Takes another Region, called other, with potentially different size and removes its "on" cells from this Region at the given x,y offset, allowing negative x and/or y to remove only part of other in this.
    remove(int x, int y, Region other, Region buffer)
    Takes another Region, called other, with potentially different size and removes its "on" cells from this Region at the given x,y offset, allowing negative x and/or y to remove only part of other in this.
    remove(Coord point)
     
    boolean
     
    boolean
     
    removeCircle(Coord center, int radius)
     
    Where a cell is "on" but forms a right-angle with exactly two orthogonally-adjacent "on" cells and exactly two orthogonally-adjacent "off" cells, this turns each of those cells "off." This won't affect east-west lines of flat "on" cells, nor north-south lines.
    Where a cell is "on" but forms a right-angle with exactly two orthogonally-adjacent "on" cells and exactly two orthogonally-adjacent "off" cells, this turns each of those cells "off." This won't affect east-west lines of flat "on" cells, nor north-south lines.
    Turns all cells that are adjacent to the boundaries of the Region to "off".
     
    removeRectangle(int startX, int startY, int rectangleWidth, int rectangleHeight)
    Removes all "on" cells from (startX, startY) inclusive to (startX+rectangleWidth, startY+rectangleHeight) exclusive, removing a total width of rectangleWidth and a total height of rectangleHeight in cells.
    removeSeveral(Coord... points)
     
     
    resizeAndEmpty(int width, int height)
    If this Region has the same width and height passed as parameters, this acts the same as empty(), makes no allocations, and returns this Region with its contents all "off"; otherwise, this does allocate a differently-sized amount of internal data to match the new width and height, sets the fields to all match the new width and height, and returns this Region with its new width and height, with all contents "off".
    boolean
     
    Takes the "on" cells in this Region and retracts them by one cell in the 4 orthogonal directions, making each "on" cell that was orthogonally adjacent to an "off" cell into an "off" cell.
    retract(int amount)
    Takes the "on" cells in this Region and retracts them by one cell in the 4 orthogonal directions, doing this iteratively amount times, making each "on" cell that was within amount orthogonal distance to an "off" cell into an "off" cell.
    retract(int amount, Region temp)
    Takes the "on" cells in this Region and retracts them by one cell in the 4 orthogonal directions, doing this iteratively amount times, making each "on" cell that was within amount orthogonal distance to an "off" cell into an "off" cell.
    Takes the "on" cells in this Region and retracts them by one cell in the 4 orthogonal directions, making each "on" cell that was orthogonally adjacent to an "off" cell into an "off" cell.
    Takes the "on" cells in this Region and retracts them by one cell in the 8 orthogonal and diagonal directions, making each "on" cell that was orthogonally or diagonally adjacent to an "off" cell into an "off" cell.
    retract8way(int amount)
    Takes the "on" cells in this Region and retracts them by one cell in the 8 orthogonal and diagonal directions, doing this iteratively amount times, making each "on" cell that was within amount orthogonal or diagonal distance to an "off" cell into an "off" cell.
    retract8way(int amount, Region temp)
    Takes the "on" cells in this Region and retracts them by one cell in the 8 orthogonal and diagonal directions, doing this iteratively amount times, making each "on" cell that was within amount orthogonal or diagonal distance to an "off" cell into an "off" cell.
    Takes the "on" cells in this Region and retracts them by one cell in the 8 orthogonal and diagonal directions, making each "on" cell that was orthogonally or diagonally adjacent to an "off" cell into an "off" cell.
    retractSeries(int amount)
    Creates an array of amount Regions, each a copy of this Region that has been retract()-ed by a progressively greater amount starting at 1 and ending at a retraction of amount from the edges.
    retractSeries8way(int amount)
    Creates an array of amount Regions, each a copy of this Region that has been retract8way()-ed by a progressively greater amount starting at 1 and ending at a retraction of amount from the edges.
    com.github.tommyettinger.ds.ObjectList<Region>
    Creates an ObjectList of Regions, each a copy of this Region that has been retracted by a progressively greater amount starting at 1 and ending at the smallest possible non-empty Region that can produce.
    com.github.tommyettinger.ds.ObjectList<Region>
    Creates an ObjectList of Regions, each a copy of this Region that has been retract8way()-ed by a progressively greater amount starting at 1 and ending at the smallest possible non-empty Region that can produce.
    separatedBlue(float fraction)
    Gets a Coord array from the "on" contents of this Region, using a quasi-random scattering of chosen cells with a count that matches the given fraction of the total amount of "on" cells in this.
    separatedBlue(float fraction, int limit)
    Gets a Coord array from the "on" contents of this Region, using a quasi-random scattering of chosen cells with a count that matches the given fraction of the total amount of "on" cells in this.
    separatedPoisson(com.github.tommyettinger.random.EnhancedRandom rng, float minimumDistance)
    Gets all but a quasi-random group of "on" cells that each has at least minimumDistance between itself and any other cell in the returned array.
    separatedPoisson(com.github.tommyettinger.random.EnhancedRandom rng, float minimumDistance, int limit)
    Gets all but a quasi-random group of "on" cells that each has at least minimumDistance between itself and any other cell in the returned array.
    separatedRegionBlue(float fraction)
    Modifies this Region so it contains a quasi-random subset of its previous contents, choosing cells so that the size() matches the given fraction of the total amount of "on" cells in this.
    separatedRegionBlue(float fraction, int limit)
    Modifies this Region so it contains a quasi-random subset of its previous contents, choosing cells so that the size() matches the given fraction of the total amount of "on" cells in this.
    separatedRegionPoisson(com.github.tommyettinger.random.EnhancedRandom rng, float minimumDistance)
    Removes all but a quasi-random group of "on" cells that each has at least minimumDistance between itself and any other cell in the returned Region.
    separatedRegionPoisson(com.github.tommyettinger.random.EnhancedRandom rng, float minimumDistance, int limit)
    Removes all but a quasi-random group of "on" cells that each has at least minimumDistance between itself and any other cell in the returned Region.
    set(boolean value, int x, int y)
    Sets the cell at x,y to on if value is true or off if value is false.
    set(boolean value, Coord point)
    Sets the cell at point to on if value is true or off if value is false.
    show(char on, char off)
    Returns this Region's data as a StringBuilder, with each row made of the parameter on for "on" cells and the parameter off for "off" cells, separated by newlines, with no trailing newline at the end.
    singleRandom(com.github.tommyettinger.random.EnhancedRandom rng)
    Gets a single random Coord from the "on" positions in this Region, or the Coord (-1,-1) if this is empty.
    int
    singleRandomTight(com.github.tommyettinger.random.EnhancedRandom rng)
     
    int
     
    spill(Region bounds, int volume, com.github.tommyettinger.random.EnhancedRandom rng)
    A randomized flood-fill that modifies this Region so it randomly adds adjacent cells while staying inside the "on" cells of bounds, until size() is equal to volume or there are no more cells this can expand into.
    spill(Region bounds, int volume, com.github.tommyettinger.random.EnhancedRandom rng, Region temp, Region temp2)
    A randomized flood-fill that modifies this Region so it randomly adds adjacent cells while staying inside the "on" cells of bounds, until size() is equal to volume or there are no more cells this can expand into.
    splash(Region bounds, com.github.tommyettinger.random.EnhancedRandom rng)
    A randomized flood-fill that modifies this Region so it randomly adds one adjacent cell if it can while staying inside the "on" cells of bounds.
    splash(Region bounds, com.github.tommyettinger.random.EnhancedRandom rng, Region temp)
    A randomized flood-fill that modifies this Region so it randomly adds one adjacent cell if it can while staying inside the "on" cells of bounds.
    com.github.tommyettinger.ds.ObjectList<Region>
    If this Region stores multiple unconnected "on" areas, this finds each isolated area (areas that are only adjacent diagonally are considered separate from each other) and returns it as an element in an ObjectList of Region, with one Region per isolated area.
    com.github.tommyettinger.ds.ObjectList<Region>
    If this Region stores multiple unconnected "on" areas, this finds each isolated area (areas that are only adjacent diagonally are considered one area with this) and returns it as an element in an ObjectList of Region, with one Region per isolated area.
    stir(Region bounds, com.github.tommyettinger.function.IntIntPredicate decider)
    A selective flood-fill that modifies this Region so it adds adjacent cells that decider evaluates to true for, if it can while staying inside the "on" cells of bounds.
    stir(Region bounds, com.github.tommyettinger.function.IntIntPredicate decider, Region temp)
    A selective flood-fill that modifies this Region so it adds adjacent cells that decider evaluates to true for, if it can while staying inside the "on" cells of bounds.
    stir(Region bounds, INoise noise, float lowerBound, float upperBound)
    A selective flood-fill that modifies this Region so it adds adjacent cells where noise.getNoise(x, y) evaluates between lowerBound (inclusive) and upperBound (exclusive), if it can while staying inside the "on" cells of bounds.
    stir(Region bounds, INoise noise, float z, float lowerBound, float upperBound)
    A selective flood-fill that modifies this Region so it adds adjacent cells where noise.getNoise(x, y, z) evaluates between lowerBound (inclusive) and upperBound (exclusive), if it can while staying inside the "on" cells of bounds.
    stir(Region bounds, INoise noise, float z, float lowerBound, float upperBound, Region temp)
    A selective flood-fill that modifies this Region so it adds adjacent cells where noise.getNoise(x, y, z) evaluates between lowerBound (inclusive) and upperBound (exclusive), if it can while staying inside the "on" cells of bounds.
    stir(Region bounds, INoise noise, float lowerBound, float upperBound, Region temp)
    A selective flood-fill that modifies this Region so it adds adjacent cells where noise.getNoise(x, y) evaluates between lowerBound (inclusive) and upperBound (exclusive), if it can while staying inside the "on" cells of bounds.
    static Region
     
     
    static int[][]
    sum(Region... regions)
    Generates a 2D int array from an array or vararg of Regions, starting at all 0 and adding 1 to the int at a position once for every Region that has that cell as "on." This means if you give 8 Regions to this method, it can produce any number between 0 and 8 in a cell; if you give 16 Regions, then it can produce any number between 0 and 16 in a cell.
    static int[][]
    sum(List<Region> regions)
    Generates a 2D int array from a List of Regions, starting at all 0 and adding 1 to the int at a position once for every Region that has that cell as "on." This means if you give 8 Regions to this method, it can produce any number between 0 and 8 in a cell; if you give 16 Regions, then it can produce any number between 0 and 16 in a cell.
    static float[][]
    sumFloat(Region... regions)
    Generates a 2D float array from an array or vararg of Regions, starting at all 0 and adding 1 to the float at a position once for every Region that has that cell as "on." This means if you give 8 Regions to this method, it can produce any number between 0 and 8 in a cell; if you give 16 Regions, then it can produce any number between 0 and 16 in a cell.
    static float[][]
    sumFloat(List<Region> regions)
    Generates a 2D float array from a List of Regions, starting at all 0 and adding 1 to the float at a position once for every Region that has that cell as "on." This means if you give 8 Regions to this method, it can produce any number between 0 and 8 in a cell; if you give 16 Regions, then it can produce any number between 0 and 16 in a cell.
    static int[][]
    sumInto(int[][] existing, Region... regions)
    Adds to an existing 2D int array with an array or vararg of Regions, adding 1 to the int in existing at a position once for every Region that has that cell as "on." This means if you give 8 Regions to this method, it can increment by any number between 0 and 8 in a cell; if you give 16 Regions, then it can increase the value in existing by any number between 0 and 16 in a cell.
    static float[][]
    sumIntoFloat(float[][] existing, Region... regions)
    Adds to an existing 2D float array with an array or vararg of Regions, adding 1 to the float in existing at a position once for every Region that has that cell as "on." This means if you give 8 Regions to this method, it can increment by any number between 0 and 8 in a cell; if you give 16 Regions, then it can increase the value in existing by any number between 0 and 16 in a cell.
    static int[][]
    sumWeighted(Region[] regions, int[] weights)
    Generates a 2D int array from an array of Regions and an array of weights, starting the 2D result at all 0 and, for every Region that has that cell as "on," adding the int in the corresponding weights array at the position of that cell.
    static float[][]
    sumWeightedFloat(Region[] regions, float[] weights)
    Generates a 2D float array from an array of Regions and an array of weights, starting the 2D result at all 0 and, for every Region that has that cell as "on," adding the float in the corresponding weights array at the position of that cell.
    Takes the "on" cells in this Region and turns them "off" if they aren't adjacent to an existing "off" cell.
    surface(int amount)
    Takes the "on" cells in this Region and turns them "off" if they aren't within amount distance of an existing "off" cell.
    surface(int amount, Region temp, Region temp2)
    Takes the "on" cells in this Region and turns them "off" if they aren't within amount distance of an existing "off" cell.
    Takes the "on" cells in this Region and turns them "off" if they aren't adjacent to an existing "off" cell.
    Takes the "on" cells in this Region and turns them "off" if they aren't adjacent to an existing "off" cell.
    surface8way(int amount)
    Takes the "on" cells in this Region and turns them "off" if they aren't within amount distance of an existing "off" cell.
    surface8way(int amount, Region temp, Region temp2)
    Takes the "on" cells in this Region and turns them "off" if they aren't within amount distance of an existing "off" cell.
    Takes the "on" cells in this Region and turns them "off" if they aren't adjacent to an existing "off" cell.
    surfaceSeries(int amount)
    Takes the "on" cells in this Region and produces amount Regions, each one a smaller and smaller result of surface() by 1 cell in the 4 orthogonal directions relative to the previous Region.
    surfaceSeries8way(int amount)
    Takes the "on" cells in this Region and produces amount Regions, each one a smaller and smaller result of surface8way() by 1 cell in the 8 orthogonal and diagonal directions relative to the previous Region.
    com.github.tommyettinger.ds.ObjectList<Region>
    Returns an ObjectList of progressively further-retracted copied surfaces of this Region.
    com.github.tommyettinger.ds.ObjectList<Region>
    Returns an ObjectList of progressively further-retracted copied surfaces of this Region.
    Like retract(), this reduces the width of thick areas of this Region, but thin() will not remove areas that would be identical in a subsequent call to retract(), such as if the area would be eliminated.
    thin(Region bufferA, Region bufferB, Region bufferC)
    Like retract(), this reduces the width of thick areas of this Region, but thin() will not remove areas that would be identical in a subsequent call to retract(), such as if the area would be eliminated.
    Like retract8way(), this reduces the width of thick areas of this Region, but thin8way() will not remove areas that would be identical in a subsequent call to retract8way(), such as if the area would be eliminated.
    thin8way(Region bufferA, Region bufferB, Region bufferC)
    Like retract8way(), this reduces the width of thick areas of this Region, but thin8way() will not remove areas that would be identical in a subsequent call to retract8way(), such as if the area would be eliminated.
    Calls thin() repeatedly, until the result is unchanged from the last call.
    thinFully(Region bufferA, Region bufferB, Region bufferC)
    Calls thin() repeatedly, until the result is unchanged from the last call.
    Calls thin8way() repeatedly, until the result is unchanged from the last call.
    thinFully8way(Region bufferA, Region bufferB, Region bufferC)
    Calls thin8way() repeatedly, until the result is unchanged from the last call.
     
    <T> T[]
    toArray(T[] a)
     
    char[][]
    Returns this Region's data as a 2D char array, [width][height] in size, with "on" cells filled with '.' and "off" cells with '#'.
    char[][]
    toChars(char on, char off)
    Returns this Region's data as a 2D char array, [width][height] in size, with "on" cells filled with the char parameter on and "off" cells with the parameter off.
    Compresses this Region into a UTF-16 String and returns the String without modifying this Region.
    toggle(int x, int y)
    Changes the on/off state of the cell with the given x and y, making an on cell into an off cell, or an off cell into an on cell.
    int[][]
    toInts(int on, int off)
    Returns this Region's data as a 2D int array, [width][height] in size, with "on" cells filled with the int parameter on and "off" cells with the parameter off.
    Returns a legible String representation of this that can be printed over multiple lines, with all "on" cells represented by '.' and all "off" cells by '#', in roguelike floors-on walls-off convention, separating each row by newlines (without a final trailing newline, so you could append text right after this).
    translate(int x, int y)
    Moves the "on" cells in this Region to the given x and y offset, removing cells that move out of bounds.
    translate(int x, int y, Region buffer)
    Moves the "on" cells in this Region to the given x and y offset, removing cells that move out of bounds.
    static com.github.tommyettinger.ds.ObjectOrderedSet<Region>
    whichContain(int x, int y, Region... packed)
     
    static com.github.tommyettinger.ds.ObjectOrderedSet<Region>
    whichContain(int x, int y, Collection<Region> packed)
     
    char[][]
    writeChars(char[][] map, char toWrite)
    Returns a copy of map where if a cell is "off" in this Region, this keeps the value in map intact, and where a cell is "on", it instead writes the char toWrite.
    char[][]
    writeCharsInto(char[][] map, char toWrite)
    Like writeChars(char[][], char), but modifies map in-place and returns it.
    char[][]
    writeCharsToOff(char[][] map, char filler)
    Returns a copy of map where if a cell is "on" in this Region, this keeps the value in map intact, and where a cell is "off", it instead writes the char filler.
    float[][]
    writeFloats(float[][] map, float toWrite)
    Returns a copy of map where if a cell is "off" in this Region, this keeps the value in map intact, and where a cell is "on", it instead writes the float toWrite.
    float[][]
    writeFloatsInto(float[][] map, float toWrite)
    Returns a copy of map where if a cell is "off" in this Region, this keeps the value in map intact, and where a cell is "on", it instead writes the float toWrite.
    int[][]
    writeInts(int[][] map, int toWrite)
    Returns a copy of map where if a cell is "off" in this Region, this keeps the value in map intact, and where a cell is "on", it instead writes the int toWrite.
    int[][]
    writeIntsInto(int[][] map, int toWrite)
    Returns a copy of map where if a cell is "off" in this Region, this keeps the value in map intact, and where a cell is "on", it instead writes the int toWrite.
    short[][]
    writeShortsToOff(short[][] map, short filler)
    Returns a copy of map where if a cell is "on" in this Region, this keeps the value in map intact, and where a cell is "off", it instead writes the short filler.
    int
    xBound(boolean findSmallest)
     
    xor(Region other)
    Symmetric difference (more commonly known as exclusive or, hence the name) of two Regions, assigning the result into this Region.
    int
    yBound(boolean findSmallest)
     
    zoom(int x, int y)
    Effectively doubles the x and y values of each cell this contains (not scaling each cell to be larger, so each "on" cell will be surrounded by "off" cells), and re-maps the positions so the given x and y in the doubled space become 0,0 in the resulting Region (which is this, assigning to itself).
    zoom(int x, int y, Region buffer)
    Effectively doubles the x and y values of each cell this contains (not scaling each cell to be larger, so each "on" cell will be surrounded by "off" cells), and re-maps the positions so the given x and y in the doubled space become 0,0 in the resulting Region (which is this, assigning to itself).

    Methods inherited from class Object

    clone, finalize, getClass, notify, notifyAll, wait, wait, wait

    Methods inherited from interface Collection

    parallelStream, removeIf, spliterator, stream, toArray

    Methods inherited from interface Iterable

    forEach
  • Field Details

    • data

      public long[] data
    • height

      public int height
    • width

      public int width
    • BLUE_LEVELS

      public static final Region[] BLUE_LEVELS
      A 256-element array of Regions, each 64x64, where the first Region has an impossibly strict threshold on what points to include (it is empty), but the second has some points far apart, the third has more, and so on until the last element includes almost all points.
  • Constructor Details

    • Region

      public Region()
      Constructs an empty 4x64 Region. Regions are mutable, so you can add to this with insert() or insertSeveral(), among others. You can also resize this and clear it with resizeAndEmpty(int, int), or replace its contents with those of another Region with remake(Region).
    • Region

      public Region(boolean[][] bits)
      Constructs a Region with the given rectangular boolean array, with width of bits.length and height of bits[0].length, any value of true considered "on", and any value of false considered "off."
      Parameters:
      bits - a rectangular 2D boolean array where true is on and false is off
    • Region

      public Region(char[][] map, char yes)
      Constructs a Region with the given rectangular char array, with width of map.length and height of map[0].length, any value that equals yes is considered "on", and any other value considered "off."
      Parameters:
      map - a rectangular 2D char array where yes is on and everything else is off
      yes - which char to encode as "on"
    • Region

      public Region(char[][] map, char[] yes)
      Constructs a Region with the given rectangular char array, with width of map.length and height of map[0].length, any value that equals yes is considered "on", and any other value considered "off."
      Parameters:
      map - a rectangular 2D char array where yes is on and everything else is off
      yes - which char to encode as "on"
    • Region

      public Region(String[] map, char yes)
      Weird constructor that takes a String array, _as it would be printed_, so each String is a row and indexing would be done with y, x instead of the normal x, y.
      Parameters:
      map - String array (as printed, not the normal storage) where each String is a row
      yes - the char to consider "on" in the Region
    • Region

      public Region(int[][] map, int yes)
      Constructs a Region with the given rectangular int array, with width of map.length and height of map[0].length, any value that equals yes is considered "on", and any other value considered "off."
      Parameters:
      map - a rectangular 2D int array where an int == yes is on and everything else is off
      yes - which int to encode as "on"
    • Region

      public Region(int[][] map, int lower, int upper)
      Constructs this Region using an int[][], treating cells as on if they are greater than or equal to lower and less than upper, or off otherwise.
      Parameters:
      map - an int[][] that should have some ints between lower and upper
      lower - lower bound, inclusive; all on cells will have values in map that are at least equal to lower
      upper - upper bound, exclusive; all on cells will have values in map that are less than upper
    • Region

      public Region(byte[][] map, int lower, int upper)
      Constructs this Region using a byte[][], treating cells as on if they are greater than or equal to lower and less than upper, or off otherwise.
      Parameters:
      map - a byte[][] that should have some bytes between lower and upper
      lower - lower bound, inclusive; all on cells will have values in map that are at least equal to lower
      upper - upper bound, exclusive; all on cells will have values in map that are less than upper
    • Region

      public Region(short[][] map, int lower, int upper)
      Constructs this Region using a short[][], treating cells as on if they are greater than or equal to lower and less than upper, or off otherwise.
      Parameters:
      map - a short[][] that should have some shorts between lower and upper
      lower - lower bound, inclusive; all on cells will have values in map that are at least equal to lower
      upper - upper bound, exclusive; all on cells will have values in map that are less than upper
    • Region

      public Region(float[][] map, float upperBound)
      Constructs this Region using a float[][] (typically one generated by DijkstraMap) that only stores two relevant states: an "on" state for values less than or equal to upperBound (inclusive), and an "off" state for anything else.
      Parameters:
      map - a float[][] that probably relates in some way to DijkstraMap.
      upperBound - upper inclusive; any float greater than this will be off, any others will be on
    • Region

      public Region(float[][] map, float lowerBound, float upperBound)
      Constructs this Region using a float[][] (typically one generated by DijkstraMap) that only stores two relevant states: an "on" state for values between lowerBound (inclusive) and upperBound (exclusive), and an "off" state for anything else.
      Parameters:
      map - a float[][] that probably relates in some way to DijkstraMap.
      lowerBound - lower inclusive; any float lower than this will be off, any equal to or greater than this, but less than upper, will be on
      upperBound - upper exclusive; any float greater than or equal to this will be off, any floats both less than this and equal to or greater than lower will be on
    • Region

      public Region(float[][] map, float lowerBound, float upperBound, int scale)
      Constructs this Region using a float[][] that only stores two relevant states: an "on" state for values between lowerBound (inclusive) and upperBound (exclusive), and an "off" state for anything else. This variant scales the input so each "on" position in map produces a 2x2 on area if scale is 2, a 3x3 area if scale is 3, and so on.
      Parameters:
      map - a float[][]; depending on scale, the Region may have different width and height
      lowerBound - lower inclusive; any float lower than this will be off, any equal to or greater than this, but less than upper, will be on
      upperBound - upper exclusive; any float greater than or equal to this will be off, any floats both less than this and equal to or greater than lower will be on
      scale - the size of the square of cells in this that each "on" value in map will correspond to
    • Region

      public Region(boolean[] bits, int width, int height)
      Constructs a Region with the given 1D boolean array, with the given width and height, where an [x][y] position is obtained from bits given an index n with x = n / height, y = n % height, any value of true considered "on", and any value of false considered "off."
      Parameters:
      bits - a 1D boolean array where true is on and false is off
      width - the width of the desired Region; width * height should equal bits.length
      height - the height of the desired Region; width * height should equal bits.length
    • Region

      public Region(com.github.tommyettinger.function.IntIntPredicate decider, int width, int height)
      Constructs a Region with the given width and height by calling decider's functional method on each x,y position for x from 0 (inclusive) to width (exclusive) and for y from 0 (inclusive) to height (exclusive). If decider returns true for an x,y position, that position will be "on", otherwise it will be "off".
      Parameters:
      decider - a function that takes an int x and an int y and returns true if that position should be "on"
      width - the width of the desired Region
      height - the height of the desired Region
    • Region

      public Region(INoise noise, float lower, float upper, int width, int height)
      Constructs a Region with the given width and height by calling INoise.getNoise(float, float) position for x from 0 (inclusive) to width (exclusive) and for y from 0 (inclusive) to height (exclusive). If this returns a float between lower (inclusive) and upper (exclusive) for an x,y position, that position will be "on", otherwise it will be "off".
      Parameters:
      noise - a noise generator that will have 2D noise queried from it with its default seed
      lower - inclusive lower bound on noise results that will be considered "on"; usually between -1 and 1
      upper - exclusive upper bound on noise results that will be considered "on"; usually between -1 and 1
      width - the width of the desired Region
      height - the height of the desired Region
    • Region

      public Region(int width, int height)
      Constructor for an empty Region of the given width and height. Regions are mutable, so you can add to this with insert() or insertSeveral(), among others.
      Parameters:
      width - the maximum width for the Region
      height - the maximum height for the Region
    • Region

      public Region(Coord single, int width, int height)
      Constructor for a Region that contains a single "on" cell, and has the given width and height. Note that to avoid confusion with the constructor that takes multiple Coord values, this takes the single "on" Coord first, while the multiple-Coord constructor takes its vararg or array of Coords last.
      Parameters:
      single - the one (x,y) point to store as "on" in this Region
      width - the maximum width for the Region
      height - the maximum height for the Region
    • Region

      public Region(int width, int height, Coord... points)
      Constructor for a Region that can have several "on" cells specified, and has the given width and height. Note that to avoid confusion with the constructor that takes one Coord value, this takes the vararg or array of Coords last, while the single-Coord constructor takes its one Coord first.
      Parameters:
      width - the maximum width for the Region
      height - the maximum height for the Region
      points - an array or vararg of Coord to store as "on" in this Region
    • Region

      public Region(int width, int height, Iterable<Coord> points)
      Constructor for a Region that can have several "on" cells specified, and has the given width and height. Note that to avoid confusion with the constructor that takes one Coord value, this takes the Iterable of Coords last, while the single-Coord constructor takes its one Coord first.
      Parameters:
      width - the maximum width for the Region
      height - the maximum height for the Region
      points - an array or vararg of Coord to store as "on" in this Region
    • Region

      public Region(com.github.tommyettinger.random.EnhancedRandom random, int width, int height)
      Constructor for a random Region of the given width and height, typically assigning approximately half of the cells in this to "on" and the rest to off.
      Parameters:
      random - a EnhancedRandom, or a recommended subclass like WhiskerRandom
      width - the maximum width for the Region
      height - the maximum height for the Region
    • Region

      public Region(com.github.tommyettinger.random.EnhancedRandom random, float fraction, int width, int height)
      Constructor for a random Region of the given width and height, trying to set the given fraction of cells to on. Depending on the value of fraction, this makes between 0 and 6 calls to the nextLong() method of random's internal EnhancedRandom, per 64 cells of this Region (if height is not a multiple of 64, round up to get the number of calls this makes). As such, this sacrifices the precision of the fraction to obtain significantly better speed than generating one random number per cell, although the precision is probably good enough (fraction is effectively rounded down to the nearest multiple of 0.015625, and clamped between 0.0 and 1.0). The parameter random can be a plain EnhancedRandom, but will be much faster and have less potential for patterns or artifacts in the output if you use WhiskerRandom or another higher-quality subclass.
      Parameters:
      random - a EnhancedRandom or a recommended subclass, like WhiskerRandom
      fraction - between 0.0 and 1.0 (clamped), only considering a precision of 1/64.0 (0.015625) between steps
      width - the maximum width for the Region
      height - the maximum height for the Region
    • Region

      public Region(Region other)
      Copy constructor that takes another Region and copies all of its data into this new one. If you find yourself frequently using this constructor and assigning it to the same variable, consider using the remake(Region) method on the variable instead, which will, if it has the same width and height as the other Region, avoid creating garbage and quickly fill the variable with the other's contents.
      Parameters:
      other - another Region that will be copied into this new Region
      See Also:
    • Region

      public Region(long[] data2, int width, int height)
      Primarily for internal use, this constructor copies data2 exactly into the internal long array the new Region will use, and does not perform any validation steps to ensure that cells that would be "on" but are outside the actual height of the Region are actually removed (this only matters if height is not a multiple of 64).
      Parameters:
      data2 - a long array that is typically from another Region, and would be hard to make otherwise
      width - the width of the Region to construct
      height - the height of the Region to construct
    • Region

      public Region(long[] data2, int dataWidth, int dataHeight, int width, int height)
      Primarily for internal use, this constructor copies data2 into the internal long array the new Region will use, but treats data2 as having the dimensions [dataWidth][dataHeight], and uses the potentially-different dimensions [width][height] for the constructed Region. This will truncate data2 on width, height, or both if width or height is smaller than dataWidth or dataHeight. It will fill extra space with all "off" if width or height is larger than dataWidth or dataHeight. It will interpret data2 as the same 2D shape regardless of the width or height it is being assigned to, and data2 will not be reshaped by truncation.
      Parameters:
      data2 - a long array that is typically from another Region, and would be hard to make otherwise
      dataWidth - the width to interpret data2 as having
      dataHeight - the height to interpret data2 as having
      width - the width of the Region to construct
      height - the height of the Region to construct
  • Method Details

    • refill

      public Region refill(boolean[][] map)
      Reassigns this Region with the given rectangular boolean array, reusing the current data storage (without extra allocations) if this.width == map.length and this.height == map[0].length. The current values stored in this are always cleared, then any value of true in map is considered "on", and any value of false in map is considered "off."
      Parameters:
      map - a rectangular 2D boolean array where true is on and false is off
      Returns:
      this for chaining
    • refill

      public Region refill(char[][] map, char yes)
      Reassigns this Region with the given rectangular char array, reusing the current data storage (without extra allocations) if this.width == map.length and this.height == map[0].length. The current values stored in this are always cleared, then any value that equals yes is considered "on", and any other value considered "off."
      Parameters:
      map - a rectangular 2D char array where yes is on and everything else is off
      yes - which char to encode as "on"
      Returns:
      this for chaining
    • refill

      public Region refill(char[][] map, char[] yes)
      Reassigns this Region with the given rectangular char array, reusing the current data storage (without extra allocations) if this.width == map.length and this.height == map[0].length. The current values stored in this are always cleared, then any value that equals yes is considered "on", and any other value considered "off."
      Parameters:
      map - a rectangular 2D char array where yes is on and everything else is off
      yes - which char to encode as "on"
      Returns:
      this for chaining
    • refill

      public Region refill(String[] map, char yes)
      Weird refill method that takes a String array, _as it would be printed_, so each String is a row and indexing would be done with y, x instead of the normal x, y.
      Parameters:
      map - String array (as printed, not the normal storage) where each String is a row
      yes - the char to consider "on" in the Region
      Returns:
      this for chaining
    • refill

      public Region refill(int[][] map, int yes)
      Reassigns this Region with the given rectangular int array, reusing the current data storage (without extra allocations) if this.width == map.length and this.height == map[0].length. The current values stored in this are always cleared, then any value that equals yes is considered "on", and any other value considered "off."
      Parameters:
      map - a rectangular 2D int array where an int == yes is on and everything else is off
      yes - which int to encode as "on"
      Returns:
      this for chaining
    • refill

      public Region refill(int[][] map, int lower, int upper)
      Reassigns this Region with the given rectangular int array, reusing the current data storage (without extra allocations) if this.width == map.length and this.height == map[0].length. The current values stored in this are always cleared, then cells are treated as on if they are greater than or equal to lower and less than upper, or off otherwise.
      Parameters:
      map - a rectangular 2D int array that should have some values between lower and upper
      lower - lower bound, inclusive; all on cells will have values in map that are at least equal to lower
      upper - upper bound, exclusive; all on cells will have values in map that are less than upper
      Returns:
      this for chaining
    • refill

      public Region refill(byte[][] map, int lower, int upper)
      Reassigns this Region with the given rectangular byte array, reusing the current data storage (without extra allocations) if this.width == map.length and this.height == map[0].length. The current values stored in this are always cleared, then cells are treated as on if they are greater than or equal to lower and less than upper, or off otherwise.
      Parameters:
      map - a rectangular 2D byte array that should have some values between lower and upper
      lower - lower bound, inclusive; all on cells will have values in map that are at least equal to lower
      upper - upper bound, exclusive; all on cells will have values in map that are less than upper
      Returns:
      this for chaining
    • refill

      public Region refill(short[][] map, int lower, int upper)
      Reassigns this Region with the given rectangular short array, reusing the current data storage (without extra allocations) if this.width == map.length and this.height == map[0].length. The current values stored in this are always cleared, then cells are treated as on if they are greater than or equal to lower and less than upper, or off otherwise.
      Parameters:
      map - a rectangular 2D short array that should have some values between lower and upper
      lower - lower bound, inclusive; all on cells will have values in map that are at least equal to lower
      upper - upper bound, exclusive; all on cells will have values in map that are less than upper
      Returns:
      this for chaining
    • refill

      public Region refill(float[][] map, float upperBound)
      Reassigns this Region with the given rectangular float array, reusing the current data storage (without extra allocations) if this.width == map.length and this.height == map[0].length. The current values stored in this are always cleared, then cells are treated as on if they are less than or equal to upperBound, or off otherwise.
      Parameters:
      map - a rectangular 2D float array that should usually have some values less than or equal to upperBound
      upperBound - upper bound, inclusive; all on cells will have values in map that are less than or equal to this
      Returns:
      this for chaining
    • refill

      public Region refill(float[][] map, float lower, float upper)
      Reassigns this Region with the given rectangular float array, reusing the current data storage (without extra allocations) if this.width == map.length and this.height == map[0].length. The current values stored in this are always cleared, then cells are treated as on if they are greater than or equal to lower and less than upper, or off otherwise.
      Parameters:
      map - a rectangular 2D float array that should have some values between lower and upper
      lower - lower bound, inclusive; all on cells will have values in map that are at least equal to lower
      upper - upper bound, exclusive; all on cells will have values in map that are less than upper
      Returns:
      this for chaining
    • refill

      public Region refill(float[][] map, float lowerBound, float upperBound, int scale)
      Reassigns this Region with the given rectangular float array, reusing the current data storage (without extra allocations) if this.width == map.length * scale && this.height == map[0].length * scale. The current values stored in this are always cleared, then cells are treated as on if they are greater than or equal to lower and less than upper, or off otherwise, before considering scaling. This variant scales the input so each "on" position in map produces a 2x2 on area if scale is 2, a 3x3 area if scale is 3, and so on.
      Parameters:
      map - a float[][]; depending on scale, the Region may have different width and height
      lowerBound - lower inclusive; any float lower than this will be off, any equal to or greater than this, but less than upper, will be on
      upperBound - upper exclusive; any float greater than or equal to this will be off, any floats both less than this and equal to or greater than lower will be on
      scale - the size of the square of cells in this that each "on" value in map will correspond to
      Returns:
      this for chaining
    • refill

      public Region refill(boolean[] bits, int width, int height)
      Reassigns this Region with the given 1D boolean array, reusing the current data storage (without extra allocations) if this.width == width and this.height == height, where an [x][y] position is obtained from bits given an index n with x = n / height, y = n % height, any value of true considered "on", and any value of false considered "off."
      Parameters:
      bits - a 1D boolean array where true is on and false is off
      width - the width of the desired Region; width * height should equal bits.length
      height - the height of the desired Region; width * height should equal bits.length
      Returns:
      this for chaining
    • refill

      public Region refill(com.github.tommyettinger.function.IntIntPredicate decider, int width, int height)
      Reassigns this Region with the given function to decide which positions will be "on", reusing the current data storage (without extra allocations) if this.width == width and this.height == height. If decider returns true for an x,y position, that position will be "on", otherwise it will be "off".
      Parameters:
      decider - a function that takes an int x and an int y and returns true if that position should be "on"
      width - the width of the desired Region
      height - the height of the desired Region
      Returns:
      this for chaining
    • refill

      public Region refill(INoise noise, float lower, float upper, int width, int height)
      Reassigns this Region with the given function to decide which positions will be "on", reusing the current data storage (without extra allocations) if this.width == width and this.height == height. If this returns a float between lower (inclusive) and upper (exclusive) for an x,y position, that position will be "on", otherwise it will be "off".
      Parameters:
      noise - a noise generator that will have 2D noise queried from it with its default seed
      lower - inclusive lower bound on noise results that will be considered "on"; usually between -1 and 1
      upper - exclusive upper bound on noise results that will be considered "on"; usually between -1 and 1
      width - the width of the desired Region
      height - the height of the desired Region
      Returns:
      this for chaining
    • resizeAndEmpty

      public Region resizeAndEmpty(int width, int height)
      If this Region has the same width and height passed as parameters, this acts the same as empty(), makes no allocations, and returns this Region with its contents all "off"; otherwise, this does allocate a differently-sized amount of internal data to match the new width and height, sets the fields to all match the new width and height, and returns this Region with its new width and height, with all contents "off". This is meant for cases where a Region may be reused effectively, but its size may not always be the same.
      Parameters:
      width - the width to potentially resize this Region to
      height - the height to potentially resize this Region to
      Returns:
      this Region, always with all contents "off", and with the height and width set.
    • refill

      public Region refill(com.github.tommyettinger.random.EnhancedRandom random, int width, int height)
      Reassigns this Region by filling it with random values from random, reusing the current data storage (without extra allocations) if this.width == width and this.height == height, and typically assigning approximately half of the cells in this to "on" and the rest to off.
      Parameters:
      random - a EnhancedRandom or a recommended subclass, like WhiskerRandom
      width - the width of the desired Region
      height - the height of the desired Region
      Returns:
      this for chaining
    • refill

      public Region refill(com.github.tommyettinger.random.EnhancedRandom random, float fraction, int width, int height)
      Reassigns this Region randomly, reusing the current data storage (without extra allocations) if this.width == width and this.height == height, while trying to set the given fraction of cells to on. Depending on the value of fraction, this makes between 0 and 6 calls to the nextLong() method of random's internal EnhancedRandom, per 64 cells of this Region (if height is not a multiple of 64, round up to get the number of calls this makes). As such, this sacrifices the precision of the fraction to obtain significantly better speed than generating one random number per cell, although the precision is probably good enough (fraction is effectively rounded down to the nearest multiple of 0.015625, and clamped between 0.0 and 1.0). The parameter random can be a plain EnhancedRandom, but will be much faster and have less potential for patterns or artifacts in the output if you use WhiskerRandom or another higher-quality subclass.
      Parameters:
      random - a EnhancedRandom or a recommended subclass, like WhiskerRandom
      fraction - between 0.0 and 1.0 (clamped), only considering a precision of 1/64.0 (0.015625) between steps
      width - the maximum width for the Region
      height - the maximum height for the Region
      Returns:
      this for chaining
    • refill

      public Region refill(long[] data2, int dataWidth, int dataHeight, int width, int height)
      Primarily for internal use, this method copies data2 into the internal long array the new Region will use, but treats data2 as having the dimensions [dataWidth][dataHeight], and uses the potentially-different dimensions [width][height] for this Region, potentially re-allocating the internal data this uses if width and/or height are different from what they were. This will truncate data2 on width, height, or both if width or height is smaller than dataWidth or dataHeight. It will fill extra space with all "off" if width or height is larger than dataWidth or dataHeight. It will interpret data2 as the same 2D shape regardless of the width or height it is being assigned to, and data2 will not be reshaped by truncation.
      Parameters:
      data2 - a long array that is typically from another Region, and would be hard to make otherwise
      dataWidth - the width to interpret data2 as having
      dataHeight - the height to interpret data2 as having
      width - the width to set this Region to have
      height - the height to set this Region to have
    • remake

      public Region remake(Region other)
      A useful method for efficiency, remake() reassigns this Region to have its contents replaced by other. If other and this Region have identical width and height, this is very efficient and performs no additional allocations, simply replacing the cell data in this with the cell data from other. If width and height are not both equal between this and other, this does allocate a new data array, but still reassigns this Region in-place and acts similarly to when width and height are both equal (it just uses some more memory).
      Using remake() or the similar refill() methods in chains of operations on multiple Regions can be key to maintaining good performance and memory usage. You often can recycle a no-longer-used Region by assigning a Region you want to keep to it with remake(), then mutating either the remade value or the one that was just filled into this but keeping one version around for later usage.
      Parameters:
      other - another Region to replace the data in this Region with
      Returns:
      this for chaining
    • alterBounds

      public Region alterBounds(int widthChange, int heightChange)
      Changes the width and/or height of this Region, enlarging or shrinking starting at the edges where x == width - 1 and y == height - 1. There isn't an especially efficient way to expand from the other edges, but this method is able to copy data in bulk, so at least this method should be very fast. You can use insert(int, int, Region) if you want to place one Region inside another one, potentially with a different size. The space created by any enlargement starts all off; shrinking doesn't change the existing data where it isn't removed by the shrink.
      Parameters:
      widthChange - the amount to change width by; can be positive, negative, or zero
      heightChange - the amount to change height by; can be positive, negative, or zero
      Returns:
      this for chaining
    • copyRotated

      public Region copyRotated(int turns)
      Makes a copy of this Region that has been rotated 90 degrees turns times. If using y-down coordinates, then these rotations are clockwise; otherwise, they are counter-clockwise. This uses a copy because in many caseswhere the Region has non-equal width and height, the rotated version has different dimensions, and that requires allocating most of a new Region anyway. This Region is never modifed as a result of this method.
      Parameters:
      turns - how many times to rotate the copy (clockwise if using y-down, counterclockwise otherwise)
      Returns:
      a potentially-rotated copy of this Region
    • flip

      public Region flip(boolean leftRight, boolean upDown)
    • set

      public Region set(boolean value, int x, int y)
      Sets the cell at x,y to on if value is true or off if value is false. Does nothing if x,y is out of bounds.
      Parameters:
      value - the value to set in the cell
      x - the x-position of the cell
      y - the y-position of the cell
      Returns:
      this for chaining
    • set

      public Region set(boolean value, Coord point)
      Sets the cell at point to on if value is true or off if value is false. Does nothing if point is out of bounds, or if point is null.
      Parameters:
      value - the value to set in the cell
      point - the x,y Coord of the cell to set
      Returns:
      this for chaining
    • insert

      public Region insert(int x, int y)
      Sets the cell at x,y to "on". Does nothing if x,y is out of bounds. More efficient, slightly, than set(boolean, int, int) if you just need to set a cell to "on".
      Parameters:
      x - the x-position of the cell
      y - the y-position of the cell
      Returns:
      this for chaining
    • insert

      public Region insert(int tight)
      Sets the given cell, "tightly" encoded for a specific width/height as by asTightEncoded(), to "on". Does nothing if the cell is out of bounds.
      Parameters:
      tight - a cell tightly encoded for this Region's width and height
      Returns:
      this for chaining
    • insert

      public Region insert(Coord point)
      Sets the cell at point to "on". Does nothing if point is out of bounds, or if point is null. More efficient, slightly, than set(boolean, Coord) if you just need to set a cell to "on".
      Parameters:
      point - the x,y Coord of the cell
      Returns:
      this for chaining
    • insert

      public Region insert(int x, int y, Region other)
      Takes another Region, called other, with potentially different size and inserts its "on" cells into this Region at the given x,y offset, allowing negative x and/or y to put only part of other in this.
      This allocates a long array internally; to avoid that, you can use insert(int, int, Region, Region).
      Parameters:
      x - the x offset to start inserting other at; may be negative
      y - the y offset to start inserting other at; may be negative
      other - the other Region to insert
      Returns:
      this for chaining
    • insert

      public Region insert(int x, int y, Region other, Region buffer)
      Takes another Region, called other, with potentially different size and inserts its "on" cells into this Region at the given x,y offset, allowing negative x and/or y to put only part of other in this.
      This overload takes a buffer Region that should be the same size as this one. If it is, this won't allocate, and after the call, buffer will contain undefined data.
      Parameters:
      x - the x offset to start inserting other at; may be negative
      y - the y offset to start inserting other at; may be negative
      other - the other Region to insert
      buffer - another Region that will be erased and replaced with the contents of this Region before this call; should be the same size as this
      Returns:
      this for chaining
    • insertSeveral

      public Region insertSeveral(Coord... points)
    • insertSeveral

      public Region insertSeveral(int[] points)
    • insertSeveral

      public Region insertSeveral(Iterable<Coord> points)
    • insertRectangle

      public Region insertRectangle(int startX, int startY, int rectangleWidth, int rectangleHeight)
    • insertCircle

      public Region insertCircle(Coord center, int radius)
    • remove

      public Region remove(int x, int y)
    • remove

      public Region remove(Coord point)
    • remove

      public Region remove(int x, int y, Region other)
      Takes another Region, called other, with potentially different size and removes its "on" cells from this Region at the given x,y offset, allowing negative x and/or y to remove only part of other in this.
      This is a rather complex method internally. The code is identical to insert(int, int, Region) except that where insert only adds cells, this only removes cells. Essentially, insert() is to or(Region) as remove() is to andNot(Region).
      This allocates a long array internally; to avoid that, you can use remove(int, int, Region, Region).
      Parameters:
      x - the x offset to start removing other from; may be negative
      y - the y offset to start removing other from; may be negative
      other - the other Region to remove
      Returns:
      this for chaining
    • remove

      public Region remove(int x, int y, Region other, Region buffer)
      Takes another Region, called other, with potentially different size and removes its "on" cells from this Region at the given x,y offset, allowing negative x and/or y to remove only part of other in this.
      This is a rather complex method internally. The code is identical to insert(int, int, Region) except that where insert only adds cells, this only removes cells. Essentially, insert() is to or(Region) as remove() is to andNot(Region).
      This overload takes a buffer Region that should be the same size as this one. If it is, this won't allocate, and after the call, buffer will contain undefined data.
      Parameters:
      x - the x offset to start removing other from; may be negative
      y - the y offset to start removing other from; may be negative
      other - the other Region to remove
      buffer - another Region that will be erased and replaced with the contents of this Region before this call; should be the same size as this
      Returns:
      this for chaining
    • removeSeveral

      public Region removeSeveral(Coord... points)
    • removeSeveral

      public Region removeSeveral(Iterable<Coord> points)
    • removeRectangle

      public Region removeRectangle(int startX, int startY, int rectangleWidth, int rectangleHeight)
      Removes all "on" cells from (startX, startY) inclusive to (startX+rectangleWidth, startY+rectangleHeight) exclusive, removing a total width of rectangleWidth and a total height of rectangleHeight in cells.
      Parameters:
      startX - left side x-coordinate
      startY - top side (or bottom if positive y is up) y-coordinate
      rectangleWidth - how many cells wide the area to remove is
      rectangleHeight - how many cells tal the area to remove is
      Returns:
      this, after modification, for chaining
    • removeCircle

      public Region removeCircle(Coord center, int radius)
    • empty

      public Region empty()
      Equivalent to clear(), setting all cells to "off," but also returns this for chaining.
      Returns:
      this for chaining
    • allOn

      public Region allOn()
      Sets all cells in this to "on."
      Returns:
      this for chaining
    • fill

      public Region fill(boolean contents)
      Sets all cells in this to "on" if contents is true, or "off" if contents is false.
      Parameters:
      contents - true to set all cells to on, false to set all cells to off
      Returns:
      this for chaining
    • removeEdges

      public Region removeEdges()
      Turns all cells that are adjacent to the boundaries of the Region to "off".
      Returns:
      this for chaining
    • copy

      public Region copy()
      Simple method that returns a newly-allocated copy of this Region; modifications to one won't change the other, and this method returns the copy while leaving the original unchanged.
      Returns:
      a copy of this Region; the copy can be changed without altering the original
    • decode

      public boolean[][] decode()
      Returns this Region's data as a 2D boolean array, [width][height] in size, with on treated as true and off treated as false.
      Returns:
      a 2D boolean array that represents this Region's data
    • intoChars

      public char[][] intoChars(char[][] chars, char on, char off)
      Fills this Region's data into the given 2D char array, modifying it and returning it, with "on" cells filled with the char parameter on and "off" cells with the parameter off.
      Parameters:
      chars - a 2D char array that will be modified; must not be null, nor can it contain null elements
      on - the char to use for "on" cells
      off - the char to use for "off" cells
      Returns:
      a 2D char array that represents this Region's data
    • intoChars

      public char[][] intoChars(char[][] chars, char on)
      Fills this Region's data into the given 2D char array, modifying it and returning it, with "on" cells filled with the char parameter on and "off" cells left as-is.
      Parameters:
      chars - a 2D char array that will be modified; must not be null, nor can it contain null elements
      on - the char to use for "on" cells
      Returns:
      a 2D char array that represents the "on" cells in this Region's data written over chars
    • toChars

      public char[][] toChars(char on, char off)
      Returns this Region's data as a 2D char array, [width][height] in size, with "on" cells filled with the char parameter on and "off" cells with the parameter off.
      Parameters:
      on - the char to use for "on" cells
      off - the char to use for "off" cells
      Returns:
      a 2D char array that represents this Region's data
    • toChars

      public char[][] toChars()
      Returns this Region's data as a 2D char array, [width][height] in size, with "on" cells filled with '.' and "off" cells with '#'.
      Returns:
      a 2D char array that represents this Region's data
    • show

      public StringBuilder show(char on, char off)
      Returns this Region's data as a StringBuilder, with each row made of the parameter on for "on" cells and the parameter off for "off" cells, separated by newlines, with no trailing newline at the end.
      Parameters:
      on - the char to use for "on" cells
      off - the char to use for "off" cells
      Returns:
      a StringBuilder that stores each row of this Region as chars, with rows separated by newlines.
    • toString

      public String toString()
      Returns a legible String representation of this that can be printed over multiple lines, with all "on" cells represented by '.' and all "off" cells by '#', in roguelike floors-on walls-off convention, separating each row by newlines (without a final trailing newline, so you could append text right after this).
      Overrides:
      toString in class Object
      Returns:
      a String representation of this Region using '.' for on, '#' for off, and newlines between rows
    • writeCharsToOff

      public char[][] writeCharsToOff(char[][] map, char filler)
      Returns a copy of map where if a cell is "on" in this Region, this keeps the value in map intact, and where a cell is "off", it instead writes the char filler.
      Parameters:
      map - a 2D char array that will not be modified
      filler - the char to use where this Region stores an "off" cell
      Returns:
      a masked copy of map, with "off" cells from this changed to filler
    • writeShortsToOff

      public short[][] writeShortsToOff(short[][] map, short filler)
      Returns a copy of map where if a cell is "on" in this Region, this keeps the value in map intact, and where a cell is "off", it instead writes the short filler. Meant for use with MultiSpill, but may be used anywhere you have a 2D short array. writeCharsToOff(char[][], char) is more likely to be useful.
      Parameters:
      map - a 2D short array that will not be modified
      filler - the short to use where this Region stores an "off" cell
      Returns:
      a masked copy of map, with "off" cells from this changed to filler
    • writeChars

      public char[][] writeChars(char[][] map, char toWrite)
      Returns a copy of map where if a cell is "off" in this Region, this keeps the value in map intact, and where a cell is "on", it instead writes the char toWrite.
      Parameters:
      map - a 2D char array that will not be modified
      toWrite - the char to use where this Region stores an "on" cell
      Returns:
      a masked copy of map, with "on" cells from this changed to toWrite
    • writeInts

      public int[][] writeInts(int[][] map, int toWrite)
      Returns a copy of map where if a cell is "off" in this Region, this keeps the value in map intact, and where a cell is "on", it instead writes the int toWrite.
      Parameters:
      map - a 2D int array that will not be modified
      toWrite - the int to use where this Region stores an "on" cell
      Returns:
      a masked copy of map, with "on" cells from this changed to toWrite
    • writeIntsInto

      public int[][] writeIntsInto(int[][] map, int toWrite)
      Returns a copy of map where if a cell is "off" in this Region, this keeps the value in map intact, and where a cell is "on", it instead writes the int toWrite. Modifies map in-place, unlike writeInts(int[][], int).
      Parameters:
      map - a 2D int array that will be modified
      toWrite - the int to use where this Region stores an "on" cell
      Returns:
      map, with "on" cells from this changed to toWrite; not a copy
    • toInts

      public int[][] toInts(int on, int off)
      Returns this Region's data as a 2D int array, [width][height] in size, with "on" cells filled with the int parameter on and "off" cells with the parameter off.
      Parameters:
      on - the int to use for "on" cells
      off - the int to use for "off" cells
      Returns:
      a 2D int array that represents this Region's data
    • writeFloats

      public float[][] writeFloats(float[][] map, float toWrite)
      Returns a copy of map where if a cell is "off" in this Region, this keeps the value in map intact, and where a cell is "on", it instead writes the float toWrite.
      Parameters:
      map - a 2D float array that will not be modified
      toWrite - the float to use where this Region stores an "on" cell
      Returns:
      an altered copy of map, with "on" cells from this changed to toWrite
    • writeFloatsInto

      public float[][] writeFloatsInto(float[][] map, float toWrite)
      Returns a copy of map where if a cell is "off" in this Region, this keeps the value in map intact, and where a cell is "on", it instead writes the float toWrite. Modifies map in-place, unlike writeFloats(float[][], float).
      Parameters:
      map - a 2D float array that will be modified
      toWrite - the float to use where this Region stores an "on" cell
      Returns:
      map, with "on" cells from this changed to toWrite; not a copy
    • writeCharsInto

      public char[][] writeCharsInto(char[][] map, char toWrite)
      Like writeChars(char[][], char), but modifies map in-place and returns it. If a cell is "off" in this Region, this keeps the value in map intact, and where a cell is "on", it instead writes the char toWrite. Modifies map in-place, unlike writeChars(char[][], char).
      Parameters:
      map - a 2D char array that will be modified
      toWrite - the char to use where this Region stores an "on" cell
      Returns:
      map, with "on" cells from this changed to toWrite; not a copy
    • or

      public Region or(Region other)
      Union of two Regions, assigning the result into this Region. Any cell that is "on" in either Region will be made "on" in this Region.
      Parameters:
      other - another Region that will not be modified
      Returns:
      this, after modification, for chaining
    • and

      public Region and(Region other)
      Intersection of two Regions, assigning the result into this Region. Any cell that is "on" in both Regions will be kept "on" in this Region, but all other cells will be made "off."
      Parameters:
      other - another Region that will not be modified
      Returns:
      this, after modification, for chaining
    • andWrapping64

      public Region andWrapping64(Region other)
      Intersection of two Regions, assigning the result into this Region, with the special requirement that other must be a 64x64 area, and the special property that other will be considered tiled to cover all of the area of this Region. Any cell that is "on" in both Regions (treating other as tiling) will be kept "on" in this Region, but all other cells will be made "off."
      Parameters:
      other - another Region that will not be modified but must be 64x64 in size; will act as if it tiles
      Returns:
      this, after modification, for chaining
    • andNot

      public Region andNot(Region other)
      Difference of two Regions, assigning the result into this Region. Any cell that is "on" in this Region and "off" in other will be kept "on" in this Region, but all other cells will be made "off."
      Parameters:
      other - another Region that will not be modified
      Returns:
      this, after modification, for chaining
      See Also:
    • notAnd

      public Region notAnd(Region other)
      Like andNot, but subtracts this Region from other and stores the result in this Region, without mutating other.
      Parameters:
      other - another Region that will not be modified
      Returns:
      this, after modification, for chaining
      See Also:
    • xor

      public Region xor(Region other)
      Symmetric difference (more commonly known as exclusive or, hence the name) of two Regions, assigning the result into this Region. Any cell that is "on" in this and "off" in other, or "off" in this and "on" in other, will be made "on" in this; all other cells will be made "off." Useful to find cells that are "on" in exactly one of two Regions (not "on" in both, or "off" in both).
      Parameters:
      other - another Region that will not be modified
      Returns:
      this, after modification, for chaining
    • not

      public Region not()
      Negates this Region, turning "on" to "off" and "off" to "on."
      Returns:
      this, after modification, for chaining
    • translate

      public Region translate(int x, int y)
      Moves the "on" cells in this Region to the given x and y offset, removing cells that move out of bounds.
      Parameters:
      x - the x offset to translate by; can be negative
      y - the y offset to translate by; can be negative
      Returns:
      this for chaining
    • translate

      public Region translate(int x, int y, Region buffer)
      Moves the "on" cells in this Region to the given x and y offset, removing cells that move out of bounds.
      This overload takes a buffer Region that should be the same size as this one. If it is, this won't allocate, and after the call, buffer will contain the previous contents of this Region.
      Parameters:
      x - the x offset to translate by; can be negative
      y - the y offset to translate by; can be negative
      buffer - another Region that will be erased and replaced with the contents of this Region before this call; should be the same size as this
      Returns:
      this for chaining
    • insertTranslation

      public Region insertTranslation(int x, int y)
      Adds to this Region with a moved set of its own "on" cells, moved to the given x and y offset. Ignores cells that would be added out of bounds. Keeps all cells that are currently "on" unchanged.
      Parameters:
      x - the x offset to translate by; can be negative
      y - the y offset to translate by; can be negative
      Returns:
      this for chaining
    • insertTranslation

      public Region insertTranslation(int x, int y, Region buffer)
      Adds to this Region with a moved set of its own "on" cells, moved to the given x and y offset. Ignores cells that would be added out of bounds. Keeps all cells that are currently "on" unchanged.
      This overload takes a buffer Region that should be the same size as this one. If it is, this won't allocate, and after the call, buffer will contain the previous contents of this Region.
      Parameters:
      x - the x offset to translate by; can be negative
      y - the y offset to translate by; can be negative
      buffer - another Region that will be erased and replaced with the contents of this Region before this call; should be the same size as this
      Returns:
      this for chaining
    • zoom

      public Region zoom(int x, int y)
      Effectively doubles the x and y values of each cell this contains (not scaling each cell to be larger, so each "on" cell will be surrounded by "off" cells), and re-maps the positions so the given x and y in the doubled space become 0,0 in the resulting Region (which is this, assigning to itself).
      Parameters:
      x - in the doubled coordinate space, the x position that should become 0 x in the result; can be negative
      y - in the doubled coordinate space, the y position that should become 0 y in the result; can be negative
      Returns:
      this for chaining
    • zoom

      public Region zoom(int x, int y, Region buffer)
      Effectively doubles the x and y values of each cell this contains (not scaling each cell to be larger, so each "on" cell will be surrounded by "off" cells), and re-maps the positions so the given x and y in the doubled space become 0,0 in the resulting Region (which is this, assigning to itself).
      This overload takes a buffer Region that should be the same size as this one. If it is, this won't allocate, and after the call, buffer will contain the previous contents of this Region.
      Parameters:
      x - in the doubled coordinate space, the x position that should become 0 x in the result; can be negative
      y - in the doubled coordinate space, the y position that should become 0 y in the result; can be negative
      buffer - another Region that will be erased and replaced with the contents of this Region before this call; should be the same size as this
      Returns:
      this for chaining
    • connect

      public Region connect()
      Takes the pairs of "on" cells in this Region that are separated by exactly one cell in an orthogonal line, and changes the gap cells to "on" as well.
      This method is very efficient due to how the class is implemented, and the various spatial increase/decrease methods (including expand(), retract(), fringe(), and surface()) all perform very well by operating in bulk on up to 64 cells at a time.
      Returns:
      this for chaining
    • connect8way

      public Region connect8way()
      Takes the pairs of "on" cells in this Region that are separated by exactly one cell in an orthogonal or diagonal line, and changes the gap cells to "on" as well.
      This method is very efficient due to how the class is implemented, and the various spatial increase/decrease methods (including expand(), retract(), fringe(), and surface()) all perform very well by operating in bulk on up to 64 cells at a time.
      Returns:
      this for chaining
    • connectLines

      public Region connectLines()
      Takes the pairs of "on" cells in this Region that are separated by exactly one cell in an orthogonal or diagonal line, and changes the gap cells to "on" as well. As a special case, this requires diagonals to either have no "on" cells adjacent along the perpendicular diagonal, or both cells on that perpendicular diagonal need to be "on." This is useful to counteract some less-desirable behavior of connect8way(), where a right angle would always get the inner corners filled because it was considered a diagonal.
      Returns:
      this for chaining
    • connectLines

      public Region connectLines(Region buffer)
      Takes the pairs of "on" cells in this Region that are separated by exactly one cell in an orthogonal or diagonal line, and changes the gap cells to "on" as well. As a special case, this requires diagonals to either have no "on" cells adjacent along the perpendicular diagonal, or both cells on that perpendicular diagonal need to be "on." This is useful to counteract some less-desirable behavior of connect8way(), where a right angle would always get the inner corners filled because it was considered a diagonal.
      This overload takes a buffer Region that should be the same size as this one. If it is, this won't allocate, and after the call, buffer will contain the previous contents of this Region.
      Parameters:
      buffer - another Region that will be erased and replaced with the contents of this Region before this call; should be the same size as this
      Returns:
      this for chaining
    • thin

      public Region thin()
      Like retract(), this reduces the width of thick areas of this Region, but thin() will not remove areas that would be identical in a subsequent call to retract(), such as if the area would be eliminated. This is useful primarily for adjusting areas so they do not exceed a width of 2 cells, though their length (the longer of the two dimensions) will be unaffected by this. Especially wide, irregularly-shaped areas may have unintended appearances if you call this repeatedly or use thinFully(); consider using this sparingly, or primarily when an area has just gotten thicker than desired.
      This currently uses 4-way adjacency, but had previously used 8-way; if you want the behavior this previously had, you can use thin8way(), but it may be a good idea to try this method as well (some of the old behavior had problems where it yielded significantly larger minimum widths in some areas).
      Returns:
      this for chaining
    • thin

      public Region thin(Region bufferA, Region bufferB, Region bufferC)
      Like retract(), this reduces the width of thick areas of this Region, but thin() will not remove areas that would be identical in a subsequent call to retract(), such as if the area would be eliminated. This is useful primarily for adjusting areas so they do not exceed a width of 2 cells, though their length (the longer of the two dimensions) will be unaffected by this. Especially wide, irregularly-shaped areas may have unintended appearances if you call this repeatedly or use thinFully(); consider using this sparingly, or primarily when an area has just gotten thicker than desired.
      This currently uses 4-way adjacency, but had previously used 8-way; if you want the behavior this previously had, you can use thin8way(), but it may be a good idea to try this method as well (some of the old behavior had problems where it yielded significantly larger minimum widths in some areas).
      This overload allows reusing temporary "buffer" Regions to avoid allocation. Each buffer Region should be the same size as this one; otherwise some allocation is still needed.
      Parameters:
      bufferA - a temporary Region that should be the same size as this Region
      bufferB - a temporary Region that should be the same size as this Region
      bufferC - a temporary Region that should be the same size as this Region
      Returns:
      this for chaining
    • thinFully

      public Region thinFully()
      Calls thin() repeatedly, until the result is unchanged from the last call. Consider using the idiom expand8way().retract().thinFully() to help change a possibly-strange appearance when the Region this is called on touches the edges of the grid. In general, this method is likely to go too far when it tries to thin a round or irregular area, and this often results in many diagonal lines spanning the formerly-thick area.
      This currently uses 4-way adjacency, but had previously used 8-way; if you want the behavior this previously had, you can use thinFully8way(), but it may be a good idea to try this method as well (some of the old behavior had problems where it yielded significantly larger minimum widths in some areas).
      Returns:
      this for chaining
    • thinFully

      public Region thinFully(Region bufferA, Region bufferB, Region bufferC)
      Calls thin() repeatedly, until the result is unchanged from the last call. Consider using the idiom expand8way().retract().thinFully() to help change a possibly-strange appearance when the Region this is called on touches the edges of the grid. In general, this method is likely to go too far when it tries to thin a round or irregular area, and this often results in many diagonal lines spanning the formerly-thick area.
      This uses 4-way adjacency. This overload allows reusing temporary "buffer" Regions to avoid allocation. Each buffer Region should be the same size as this one; otherwise some allocation is still needed.
      Parameters:
      bufferA - a temporary Region that should be the same size as this Region
      bufferB - a temporary Region that should be the same size as this Region
      bufferC - a temporary Region that should be the same size as this Region
      Returns:
      this for chaining
    • thin8way

      public Region thin8way()
      Like retract8way(), this reduces the width of thick areas of this Region, but thin8way() will not remove areas that would be identical in a subsequent call to retract8way(), such as if the area would be eliminated. This is useful primarily for adjusting areas so they do not exceed a width of 2 cells, though their length (the longer of the two dimensions) will be unaffected by this. Especially wide, irregularly-shaped areas may have unintended appearances if you call this repeatedly or use thinFully8way(); consider using this sparingly, or primarily when an area has just gotten thicker than desired.
      This method was called thin(), but now that name refers to a variant that uses 4-way adjacency.
      Returns:
      this for chaining
    • thin8way

      public Region thin8way(Region bufferA, Region bufferB, Region bufferC)
      Like retract8way(), this reduces the width of thick areas of this Region, but thin8way() will not remove areas that would be identical in a subsequent call to retract8way(), such as if the area would be eliminated. This is useful primarily for adjusting areas so they do not exceed a width of 2 cells, though their length (the longer of the two dimensions) will be unaffected by this. Especially wide, irregularly-shaped areas may have unintended appearances if you call this repeatedly or use thinFully8way(); consider using this sparingly, or primarily when an area has just gotten thicker than desired.
      This uses 8-way adjacency. This overload allows reusing temporary "buffer" Regions to avoid allocation. Each buffer Region should be the same size as this one; otherwise, some allocation is still needed.
      Parameters:
      bufferA - a temporary Region that should be the same size as this Region
      bufferB - a temporary Region that should be the same size as this Region
      bufferC - a temporary Region that should be the same size as this Region
      Returns:
      this for chaining
    • thinFully8way

      public Region thinFully8way()
      Calls thin8way() repeatedly, until the result is unchanged from the last call. Consider using the idiom expand8way().retract().thinFully8way() to help change a strange appearance when the Region this is called on touches the edges of the grid. In general, this method is likely to go too far when it tries to thin a round or irregular area, and this often results in many diagonal lines spanning the formerly-thick area.
      This method was called thinFully(), but now that name refers to a variant that uses 4-way adjacency.
      Returns:
      this for chaining
    • thinFully8way

      public Region thinFully8way(Region bufferA, Region bufferB, Region bufferC)
      Calls thin8way() repeatedly, until the result is unchanged from the last call. Consider using the idiom expand8way(bufferA).retract(bufferA).thinFully8way(bufferA, bufferB, bufferC) to help change a possibly-strange appearance when the Region this is called on touches the edges of the grid. In general, this method is likely to go too far when it tries to thin a round or irregular area, and this often results in many diagonal lines spanning the formerly-thick area.
      This uses 8-way adjacency. This overload allows reusing temporary "buffer" Regions to avoid allocation. Each buffer Region should be the same size as this one; otherwise, some allocation is still needed.
      Parameters:
      bufferA - a temporary Region that should be the same size as this Region
      bufferB - a temporary Region that should be the same size as this Region
      bufferC - a temporary Region that should be the same size as this Region
      Returns:
      this for chaining
    • disperse

      public Region disperse()
      Removes "on" cells that are orthogonally adjacent to other "on" cells, keeping at least one cell in a group "on." Uses a "checkerboard" pattern to determine which cells to turn off, with all cells that would be black on a checkerboard turned off and all others kept as-is.
      Returns:
      this for chaining
    • disperse8way

      public Region disperse8way()
      Removes "on" cells that are 8-way adjacent to other "on" cells, keeping at least one cell in a group "on." Uses a "grid-like" pattern to determine which cells to turn off, with all cells with even x and even y kept as-is but all other cells (with either or both odd x or odd y) turned off.
      Returns:
      this for chaining
    • disperseRandom

      public Region disperseRandom(com.github.tommyettinger.random.EnhancedRandom random)
      Removes "on" cells that are nearby other "on" cells, with a random factor to which bits are actually turned off that still ensures exactly half of the bits are kept as-is (the one exception is when height is an odd number, which makes the bottom row slightly random).
      Parameters:
      random - the RNG used for a random factor
      Returns:
      this for chaining
    • approximateBits

      public static long approximateBits(com.github.tommyettinger.random.EnhancedRandom random, int bitCount)
      Generates a random 64-bit long with a number of '1' bits (Hamming weight) equal on average to bitCount. For example, calling this with a parameter of 32 will be equivalent to calling nextLong() on the given EnhancedRandom, which is recommended to be a subclass like WhiskerRandom. Calling this with a parameter of 16 will have on average 16 of the 64 bits in the returned long set to '1', distributed pseudo-randomly, while a parameter of 47 will have on average 47 bits set. This can be useful for certain code that uses bits to represent data but needs a different ratio of set bits to unset bits than 1:1.
      The parameter random can be a plain EnhancedRandom, but will be much faster and have less potential for patterns or artifacts in the output if you use WhiskerRandom or another higher-quality subclass.
      Parameters:
      random - a EnhancedRandom or a recommended subclass, like WhiskerRandom
      bitCount - an int, only considered if between 0 and 64, that is the average number of bits to set
      Returns:
      a 64-bit long that, on average, should have bitCount bits set to 1, potentially anywhere in the long
    • randomInterleave

      public static long randomInterleave(com.github.tommyettinger.random.EnhancedRandom random)
      Gets a somewhat-random long with exactly 32 bits set; in each pair of bits starting at bit 0 and bit 1, then bit 2 and bit 3, up to bit 62 and bit 3, one bit will be 1 and one bit will be 0 in each pair.
      Not exactly general-use; meant for generating data for Region.
      Returns:
      a random long with 32 "1" bits, distributed so exactly one bit is "1" for each pair of bits
    • expand

      public Region expand()
      Takes the "on" cells in this Region and expands them by one cell in the 4 orthogonal directions, making each "on" cell take up a plus-shaped area that may overlap with other "on" cells (which is just a normal "on" cell then).
      This operates in bulk on up to 64 cells at a time. This overload allocates an array the same size as the one used internally in this Region. To avoid allocating anything, you can reuse a Region the same size as this one and pass it to expand(Region).
      Returns:
      this for chaining
    • expand

      public Region expand(Region temp)
      Takes the "on" cells in this Region and expands them by one cell in the 4 orthogonal directions, making each "on" cell take up a plus-shaped area that may overlap with other "on" cells (which is just a normal "on" cell then).
      This operates in bulk on up to 64 cells at a time. This overload takes a temporary Region temp that should be the same size as this Region. If temp is non-null, it will be cleared and receive the contents of this Region before this method call.
      Parameters:
      temp - a temporary Region that should be the same size as this one
      Returns:
      this for chaining
    • expand

      public Region expand(int amount)
      Takes the "on" cells in this Region and expands them by amount cells in the 4 orthogonal directions, making each "on" cell take up a plus-shaped area that may overlap with other "on" cells (which is just a normal "on" cell then).
      This operates in bulk on up to 64 cells at a time. This method allocates and discards a temporary copy of this Region. There is an overload of this method, expand(int, Region), that takes a reusable buffer Region to avoid allocations; it can be preferable if you intend to call expand(int) repeatedly.
      Returns:
      this for chaining
    • expand

      public Region expand(int amount, Region temp)
      Takes the "on" cells in this Region and expands them by amount cells in the 4 orthogonal directions, making each "on" cell take up a plus-shaped area that may overlap with other "on" cells (which is just a normal "on" cell then).
      This operates in bulk on up to 64 cells at a time. This overload takes a temporary Region temp that should be the same size as this Region. If temp is non-null, it will be cleared and receive the contents of this Region before this method call.
      Parameters:
      temp - a temporary Region that should be the same size as this one
      Returns:
      this for chaining
    • expandSeries

      public Region[] expandSeries(int amount)
      Takes the "on" cells in this Region and produces amount Regions, each one expanded by 1 cell in the 4 orthogonal directions relative to the previous Region, making each "on" cell take up a plus-shaped area that may overlap with other "on" cells (which is just a normal "on" cell then). This returns an array of Regions with progressively greater expansions, and does not modify this Region.
      This operates in bulk on up to 64 cells at a time. This method allocates multiple copied Regions and returns most of them in an array.
      Returns:
      an array of new Regions, length == amount, where each one is expanded by 1 relative to the last
    • expandSeriesToLimit

      public com.github.tommyettinger.ds.ObjectList<Region> expandSeriesToLimit()
      Returns a new ObjectList of Region where each item is a progressively more and more expand()-ed copy of this Region, until ending where the entire Region is "on" cells.
      Returns:
      a new ObjectList of copies of this Region, each expanded more and more until every cell is "on"
    • fringe

      public Region fringe()
      Takes the "on" cells in this Region and expands them by one cell in the 4 orthogonal directions, producing a diamond shape, then removes the original area before expansion, producing only the cells that were "off" in this and within 1 cell (orthogonal-only) of an "on" cell. This method is similar to surface(), but surface finds cells inside the current Region, while fringe finds cells outside it.
      This operates in bulk on up to 64 cells at a time. This method allocates and discards a temporary copy of this Region. There is an overload of this method, fringe(Region), that takes a reusable buffer Region to avoid allocations; it can be preferable if you intend to call fringe() repeatedly.
      Returns:
      this for chaining
    • fringe

      public Region fringe(Region temp)
      Takes the "on" cells in this Region and expands them by one cell in the 4 orthogonal directions, producing a diamond shape, then removes the original area before expansion, producing only the cells that were "off" in this and within 1 cell (orthogonal-only) of an "on" cell. This method is similar to surface(), but surface finds cells inside the current Region, while fringe finds cells outside it.
      This operates in bulk on up to 64 cells at a time. This overload takes a temporary Region temp that should be the same size as this Region. If temp is non-null, it will be cleared and receive the contents of this Region before this method call.
      Parameters:
      temp - another Region that will be erased and replaced with the contents of this Region before this call; should be the same size as this
      Returns:
      this for chaining
    • fringe

      public Region fringe(int amount)
      Takes the "on" cells in this Region and expands them by amount cells in the 4 orthogonal directions (iteratively, producing a diamond shape), then removes the original area before expansion, producing only the cells that were "off" in this and within amount cells (orthogonal-only) of an "on" cell. This method is similar to surface(), but surface finds cells inside the current Region, while fringe finds cells outside it.
      This operates in bulk on up to 64 cells at a time. This method allocates and discards a temporary copy of this Region. There is an overload of this method, fringe(Region), that takes a reusable buffer Region to avoid allocations; it can be preferable if you intend to call fringe() repeatedly.
      Parameters:
      amount - how thick the bordering area should be
      Returns:
      this for chaining
    • fringe

      public Region fringe(int amount, Region temp, Region temp2)
      Takes the "on" cells in this Region and expands them by amount cells in the 4 orthogonal directions (iteratively, producing a diamond shape), then removes the original area before expansion, producing only the cells that were "off" in this and within amount cells (orthogonal-only) of an "on" cell. This method is similar to surface(), but surface finds cells inside the current Region, while fringe finds cells outside it.
      This operates in bulk on up to 64 cells at a time. This overload of fringe allows taking a temp and temp2 Region that should be the same size as this Region, and won't allocate by modifying temp and temp2 in-place. While temp, if non-null, will reliably contain the same contents as this Region before this method call, temp2 won't have any guarantee. All values in temp2 will be eliminated, so it really should be considered temporary. If temp or temp2 is a different size from this Region, some memory will be allocated; allocation will also occur if any of temp or temp2 is null.
      Parameters:
      amount - how thick the bordering area should be
      temp - another Region that will be erased and replaced with the contents of this Region before this call; should be the same size as this
      temp2 - another Region that will be erased and replaced with undefined contents; should be the same size as this
      Returns:
      this for chaining
    • fringeSeries

      public Region[] fringeSeries(int amount)
      Takes the "on" cells in this Region and produces amount Regions, each one expanded by 1 cell in the 4 orthogonal directions relative to the previous Region, making each "on" cell take up a diamond-shaped area. After producing the expansions, this removes the previous Region from the next Region in the array, making each "fringe" in the series have 1 "thickness," which can be useful for finding which layer of expansion a cell lies in. This returns an array of Regions with progressively greater expansions without the cells of this Region, and does not modify this Region.
      This operates in bulk on up to 64 cells at a time. This method allocates multiple copied Regions and returns most of them in an array.
      Returns:
      an array of new Regions, length == amount, where each one is a 1-depth fringe pushed further out from this
    • fringeSeriesToLimit

      public com.github.tommyettinger.ds.ObjectList<Region> fringeSeriesToLimit()
      Returns an ObjectList of progressively further-expanded copied fringes of this Region. This works like expandSeriesToLimit(), and produces the same number of Region copies as that method, but removes everything but the edge of each copy. Uses 4-way adjacency, adding only orthogonally-adjacent cells.
      Returns:
      a new ObjectList of copies of this Region, each expanded more and more until expansion can't add cells, and with everything but the latest expansion removed
    • retract

      public Region retract()
      Takes the "on" cells in this Region and retracts them by one cell in the 4 orthogonal directions, making each "on" cell that was orthogonally adjacent to an "off" cell into an "off" cell.
      This operates in bulk on up to 64 cells at a time. This overload allocates an array the same size as the one used internally in this Region.
      Returns:
      this for chaining
    • retract

      public Region retract(Region temp)
      Takes the "on" cells in this Region and retracts them by one cell in the 4 orthogonal directions, making each "on" cell that was orthogonally adjacent to an "off" cell into an "off" cell.
      This operates in bulk on up to 64 cells at a time. This overload takes a temporary Region temp that should be the same size as this Region. If temp is non-null, it will be cleared and receive the contents of this Region before this method call.
      Parameters:
      temp - a temporary Region that should be the same size as this one
      Returns:
      this for chaining
    • retract

      public Region retract(int amount)
      Takes the "on" cells in this Region and retracts them by one cell in the 4 orthogonal directions, doing this iteratively amount times, making each "on" cell that was within amount orthogonal distance to an "off" cell into an "off" cell.
      This operates in bulk on up to 64 cells at a time. This allocates and discards a temporary Region with the same size as this one.
      Returns:
      this for chaining
    • retract

      public Region retract(int amount, Region temp)
      Takes the "on" cells in this Region and retracts them by one cell in the 4 orthogonal directions, doing this iteratively amount times, making each "on" cell that was within amount orthogonal distance to an "off" cell into an "off" cell.
      This overload takes a temporary Region temp that should be the same size as this Region. If temp is non-null, it will be cleared and receive the contents of this Region before this method call.
      Parameters:
      temp - a temporary Region that should be the same size as this one
      Returns:
      this for chaining
    • retractSeries

      public Region[] retractSeries(int amount)
      Creates an array of amount Regions, each a copy of this Region that has been retract()-ed by a progressively greater amount starting at 1 and ending at a retraction of amount from the edges. This method allocates multiple copied Regions and returns most of them in an array.
      Parameters:
      amount - how many Region copies should be in the returned array; should be non-negative
      Returns:
      a new Region array containing progressively more and more retract()-ed copies of this Region
    • retractSeriesToLimit

      public com.github.tommyettinger.ds.ObjectList<Region> retractSeriesToLimit()
      Creates an ObjectList of Regions, each a copy of this Region that has been retracted by a progressively greater amount starting at 1 and ending at the smallest possible non-empty Region that can produce.
      Returns:
      a new Region ObjectList containing progressively more and more retract()-ed copies of this Region
    • surface

      public Region surface()
      Takes the "on" cells in this Region and turns them "off" if they aren't adjacent to an existing "off" cell. This uses 4-way adjacency, and will never add "on" cells to the Region (it can only remove them or leave them as-is). This method acts like fringe() but only produces "on" cells where there were "on" cells at the edge of this Region's existing "on" cells.
      This operates in bulk on up to 64 cells at a time. This method allocates and discards a temporary copy of this Region. There is an overload of this method, surface(Region), that takes a reusable buffer Region to avoid allocations; it can be preferable if you intend to call surface() repeatedly.
      Returns:
      this for chaining
    • surface

      public Region surface(Region temp)
      Takes the "on" cells in this Region and turns them "off" if they aren't adjacent to an existing "off" cell. This uses 4-way adjacency, and will never add "on" cells to the Region (it can only remove them or leave them as-is). This method acts like fringe() but only produces "on" cells where there were "on" cells at the edge of this Region's existing "on" cells.
      This operates in bulk on up to 64 cells at a time. This overload takes a temporary Region temp that should be the same size as this Region. If temp is non-null, it will be cleared and receive the contents of this Region before this method call.
      Parameters:
      temp - another Region that will be erased and replaced with the contents of this Region before this call; should be the same size as this
      Returns:
      this for chaining
    • surface

      public Region surface(int amount)
      Takes the "on" cells in this Region and turns them "off" if they aren't within amount distance of an existing "off" cell. This uses 4-way adjacency, and will never add "on" cells to the Region (it can only remove them or leave them as-is). This method acts like fringe(int) but only produces "on" cells where there were "on" cells at the edge of this Region's existing "on" cells.
      This overload allocates a temporary buffer Region; surface(int, Region, Region) does not.
      Parameters:
      amount - how thick the bordering area should be
      Returns:
      this for chaining
    • surface

      public Region surface(int amount, Region temp, Region temp2)
      Takes the "on" cells in this Region and turns them "off" if they aren't within amount distance of an existing "off" cell. This uses 4-way adjacency, and will never add "on" cells to the Region (it can only remove them or leave them as-is). This method acts like fringe(int) but only produces "on" cells where there were "on" cells at the edge of this Region's existing "on" cells.
      This operates in bulk on up to 64 cells at a time. This overload of surface allows taking a temp and temp2 Region that should be the same size as this Region, and won't allocate by modifying temp and temp2 in-place. While temp, if non-null, will reliably contain the same contents as this Region before this method call, temp2 won't have any guarantee. All values in temp2 will be eliminated, so it really should be considered temporary. If temp or temp2 is a different size from this Region, some memory will be allocated; allocation will also occur if any of temp or temp2 is null.
      Parameters:
      amount - how thick the bordering area should be
      temp - another Region that will be erased and replaced with the contents of this Region before this call; should be the same size as this
      temp2 - another Region that will be erased and replaced with undefined contents; should be the same size as this
      Returns:
      this for chaining
    • surfaceSeries

      public Region[] surfaceSeries(int amount)
      Takes the "on" cells in this Region and produces amount Regions, each one a smaller and smaller result of surface() by 1 cell in the 4 orthogonal directions relative to the previous Region. After producing the expansions, this removes the previous Region from the next Region in the array, making each "surface" in the series have 1 "thickness," which can be useful for finding which layer of surfacing a cell lies in. This returns an array of Regions with progressively smaller perimeters taken from the cells of this Region, and does not modify this Region.
      This operates in bulk on up to 64 cells at a time. This method allocates multiple copied Regions and returns most of them in an array.
      Returns:
      an array of new Regions, length == amount, where each one is a 1-depth fringe pushed further out from this
    • surfaceSeriesToLimit

      public com.github.tommyettinger.ds.ObjectList<Region> surfaceSeriesToLimit()
      Returns an ObjectList of progressively further-retracted copied surfaces of this Region. This works like retractSeriesToLimit(), but produces one more Region copy than that method, and only retains the changed surface of the just-retracted area. This uses 4-way adjacency.
      Returns:
      a new ObjectList of copies of this Region, each retracted more and more until only a surface is left, and with everything but the latest change removed from each copy
    • expand8way

      public Region expand8way()
      Takes the "on" cells in this Region and expands them by one cell in the 8 orthogonal and diagonal directions, making each "on" cell take up a 3x3 square-shaped area that may overlap with other "on" cells (which is just a normal "on" cell then).
      This operates in bulk on up to 64 cells at a time. This overload allocates an array the same size as the one used internally in this Region. To avoid allocating anything, you can reuse a Region the same size as this one and pass it to expand8way(Region).
      Returns:
      this for chaining
    • expand8way

      public Region expand8way(Region temp)
      Takes the "on" cells in this Region and expands them by one cell in the 8 orthogonal and diagonal directions, making each "on" cell take up a 3x3 square-shaped area that may overlap with other "on" cells (which is just a normal "on" cell then).
      This operates in bulk on up to 64 cells at a time. This overload takes a temporary Region temp that should be the same size as this Region. If temp is non-null, it will be cleared and receive the contents of this Region before this method call.
      Parameters:
      temp - a temporary Region that should be the same size as this one
      Returns:
      this for chaining
    • expand8way

      public Region expand8way(int amount)
      Takes the "on" cells in this Region and expands them by amount cells in the 8 orthogonal and diagonal directions, making each "on" cell take up a square-shaped area that may overlap with other "on" cells (which is just a normal "on" cell then).
      This operates in bulk on up to 64 cells at a time. This overload allocates an array the same size as the one used internally in this Region. To avoid allocating anything, you can reuse a Region the same size as this one and pass it to expand8way(int, Region).
      Parameters:
      amount - how thick the bordering area should be
      Returns:
      this for chaining
    • expand8way

      public Region expand8way(int amount, Region temp)
      Takes the "on" cells in this Region and expands them by amount cells in the 8 orthogonal and diagonal directions, making each "on" cell take up a square-shaped area that may overlap with other "on" cells (which is just a normal "on" cell then).
      This operates in bulk on up to 64 cells at a time. This overload takes a temporary Region temp that should be the same size as this Region. If temp is non-null, it will be cleared and receive the contents of this Region before this method call.
      Parameters:
      amount - how thick the bordering area should be
      temp - a temporary Region that should be the same size as this one
      Returns:
      this for chaining
    • expandSeries8way

      public Region[] expandSeries8way(int amount)
      Takes the "on" cells in this Region and produces amount Regions, each one expanded by 1 cell in the 8 orthogonal and diagonal directions relative to the previous Region, making each "on" cell take up a square-shaped area that may overlap with other "on" cells (which is just a normal "on" cell then). This returns an array of Regions with progressively greater expansions, and does not modify this Region.
      This operates in bulk on up to 64 cells at a time. This method allocates multiple copied Regions and returns most of them in an array.
      Returns:
      an array of new Regions, length == amount, where each one is expanded by 1 relative to the last
    • expandSeriesToLimit8way

      public com.github.tommyettinger.ds.ObjectList<Region> expandSeriesToLimit8way()
      Returns a new ObjectList of Region where each item is a progressively more and more expand8way()-ed copy of this Region, until just before the entire Region is "on" cells.
      Returns:
      a new ObjectList of copies of this Region, each expanded more and more until expansion can't add cells
    • fringe8way

      public Region fringe8way()
      Takes the "on" cells in this Region and expands them by one cell in the 8 orthogonal and diagonal directions, producing a square shape, then removes the original area before expansion, producing only the cells that were "off" in this and within 1 cell (8-way) of an "on" cell. This method is similar to surface8way(), but surface finds cells inside the current Region, while fringe finds cells outside it.
      This operates in bulk on up to 64 cells at a time. This method allocates and discards a temporary copy of this Region. There is an overload of this method, fringe8way(Region), that takes a reusable buffer Region to avoid allocations; it can be preferable if you intend to call fringe8way() repeatedly.
      Returns:
      this for chaining
    • fringe8way

      public Region fringe8way(Region temp)
      Takes the "on" cells in this Region and expands them by one cell in the 8 orthogonal and diagonal directions, producing a square shape, then removes the original area before expansion, producing only the cells that were "off" in this and within 1 cell (8-way) of an "on" cell. This method is similar to surface8way(), but surface finds cells inside the current Region, while fringe finds cells outside it.
      This operates in bulk on up to 64 cells at a time. This overload takes a temporary Region temp that should be the same size as this Region. If temp is non-null, it will be cleared and receive the contents of this Region before this method call.
      Parameters:
      temp - another Region that will be erased and replaced with the contents of this Region before this call; should be the same size as this
      Returns:
      this for chaining
    • fringe8way

      public Region fringe8way(int amount)
      Takes the "on" cells in this Region and expands them by amount cells in the 8 orthogonal and diagonal directions (iteratively, producing a square shape), then removes the original area before expansion, producing only the cells that were "off" in this and within amount cells (8-way) of an "on" cell. This method is similar to surface8way(), but surface finds cells inside the current Region, while fringe finds cells outside it.
      This operates in bulk on up to 64 cells at a time. This method allocates and discards a temporary copy of this Region. There is an overload of this method, fringe8way(int, Region, Region), that takes reusable buffer Regions to avoid allocations; it can be preferable if you intend to call fringe8way() repeatedly.
      Parameters:
      amount - how thick the bordering area should be
      Returns:
      this for chaining
    • fringe8way

      public Region fringe8way(int amount, Region temp, Region temp2)
      Takes the "on" cells in this Region and expands them by amount cells in the 8 orthogonal and diagonal directions (iteratively, producing a square shape), then removes the original area before expansion, producing only the cells that were "off" in this and within amount cells (8-way) of an "on" cell. This method is similar to surface8way(), but surface finds cells inside the current Region, while fringe finds cells outside it.
      This operates in bulk on up to 64 cells at a time. This overload of fringe8way allows taking a temp and temp2 Region that should be the same size as this Region, and won't allocate by modifying temp and temp2 in-place. While temp, if non-null, will reliably contain the same contents as this Region before this method call, temp2 won't have any guarantee. All values in temp2 will be eliminated, so it really should be considered temporary. If temp or temp2 is a different size from this Region, some memory will be allocated; allocation will also occur if any of temp or temp2 is null.
      Parameters:
      amount - how thick the bordering area should be
      temp - another Region that will be erased and replaced with the contents of this Region before this call; should be the same size as this
      temp2 - another Region that will be erased and replaced with undefined contents; should be the same size as this
      Returns:
      this for chaining
    • fringeSeries8way

      public Region[] fringeSeries8way(int amount)
      Takes the "on" cells in this Region and produces amount Regions, each one expanded by 1 cell in the 8 orthogonal and diagonal directions relative to the previous Region, making each "on" cell take up a square-shaped area. After producing the expansions, this removes the previous Region from the next Region in the array, making each "fringe" in the series have 1 "thickness," which can be useful for finding which layer of expansion a cell lies in. This returns an array of Regions with progressively greater expansions without the cells of this Region, and does not modify this Region.
      This operates in bulk on up to 64 cells at a time. This method allocates multiple copied Regions and returns most of them in an array.
      Returns:
      an array of new Regions, length == amount, where each one is a 1-depth fringe pushed further out from this
    • fringeSeriesToLimit8way

      public com.github.tommyettinger.ds.ObjectList<Region> fringeSeriesToLimit8way()
      Returns an ObjectList of progressively further-expanded copied fringes of this Region. This works like expandSeriesToLimit8way(), and produces the same number of Region copies as that method, but removes everything but the edge of each copy. Uses 8-way adjacency, adding orthogonally- and diagonally-adjacent cells.
      Returns:
      a new ObjectList of copies of this Region, each expanded more and more until expansion can't add cells, and with everything but the latest expansion removed
    • retract8way

      public Region retract8way()
      Takes the "on" cells in this Region and retracts them by one cell in the 8 orthogonal and diagonal directions, making each "on" cell that was orthogonally or diagonally adjacent to an "off" cell into an "off" cell.
      This operates in bulk on up to 64 cells at a time. This overload allocates an array the same size as the one used internally in this Region. To avoid allocating anything, you can reuse a Region the same size as this one and pass it to retract8way(Region).
      Returns:
      this for chaining
    • retract8way

      public Region retract8way(Region temp)
      Takes the "on" cells in this Region and retracts them by one cell in the 8 orthogonal and diagonal directions, making each "on" cell that was orthogonally or diagonally adjacent to an "off" cell into an "off" cell.
      This operates in bulk on up to 64 cells at a time. This overload takes a temporary Region temp that should be the same size as this Region. If temp is non-null, it will be cleared and receive the contents of this Region before this method call.
      Parameters:
      temp - a temporary Region that should be the same size as this one
      Returns:
      this for chaining
    • retract8way

      public Region retract8way(int amount)
      Takes the "on" cells in this Region and retracts them by one cell in the 8 orthogonal and diagonal directions, doing this iteratively amount times, making each "on" cell that was within amount orthogonal or diagonal distance to an "off" cell into an "off" cell.
      This operates in bulk on up to 64 cells at a time. This allocates and discards a temporary Region with the same size as this one.
      Returns:
      this for chaining
    • retract8way

      public Region retract8way(int amount, Region temp)
      Takes the "on" cells in this Region and retracts them by one cell in the 8 orthogonal and diagonal directions, doing this iteratively amount times, making each "on" cell that was within amount orthogonal or diagonal distance to an "off" cell into an "off" cell.
      This overload takes a temporary Region temp that should be the same size as this Region. If temp is non-null, it will be cleared and receive the contents of this Region before this method call.
      Parameters:
      temp - a temporary Region that should be the same size as this one
      Returns:
      this for chaining
    • retractSeries8way

      public Region[] retractSeries8way(int amount)
      Creates an array of amount Regions, each a copy of this Region that has been retract8way()-ed by a progressively greater amount starting at 1 and ending at a retraction of amount from the edges. This method allocates multiple copied Regions and returns most of them in an array.
      Parameters:
      amount - how many Region copies should be in the returned array; should be non-negative
      Returns:
      a new Region array containing progressively more and more retract()-ed copies of this Region
    • retractSeriesToLimit8way

      public com.github.tommyettinger.ds.ObjectList<Region> retractSeriesToLimit8way()
      Creates an ObjectList of Regions, each a copy of this Region that has been retract8way()-ed by a progressively greater amount starting at 1 and ending at the smallest possible non-empty Region that can produce.
      Returns:
      a new Region ObjectList containing progressively more and more retract8way()-ed copies of this Region
    • surface8way

      public Region surface8way()
      Takes the "on" cells in this Region and turns them "off" if they aren't adjacent to an existing "off" cell. This uses 8-way adjacency, and will never add "on" cells to the Region (it can only remove them or leave them as-is). This method acts like fringe8way() but only produces "on" cells where there were "on" cells at the edge of this Region's existing "on" cells.
      This operates in bulk on up to 64 cells at a time. This method allocates and discards a temporary copy of this Region. There is an overload of this method, surface8way(Region), that takes a reusable buffer Region to avoid allocations; it can be preferable if you intend to call surface8way() repeatedly.
      Returns:
      this for chaining
    • surface8way

      public Region surface8way(Region temp)
      Takes the "on" cells in this Region and turns them "off" if they aren't adjacent to an existing "off" cell. This uses 8-way adjacency, and will never add "on" cells to the Region (it can only remove them or leave them as-is). This method acts like fringe() but only produces "on" cells where there were "on" cells at the edge of this Region's existing "on" cells.
      This operates in bulk on up to 64 cells at a time. This overload takes a temporary Region temp that should be the same size as this Region. If temp is non-null, it will be cleared and receive the contents of this Region before this method call.
      Parameters:
      temp - another Region that will be erased and replaced with the contents of this Region before this call; should be the same size as this
      Returns:
      this for chaining
    • surface8way

      public Region surface8way(int amount)
      Takes the "on" cells in this Region and turns them "off" if they aren't within amount distance of an existing "off" cell. This uses 8-way adjacency, and will never add "on" cells to the Region (it can only remove them or leave them as-is). This method acts like fringe8way(int) but only produces "on" cells where there were "on" cells at the edge of this Region's existing "on" cells.
      This overload allocates a temporary buffer Region; surface8way(int, Region, Region) does not.
      Parameters:
      amount - how thick the bordering area should be
      Returns:
      this for chaining
    • surface8way

      public Region surface8way(int amount, Region temp, Region temp2)
      Takes the "on" cells in this Region and turns them "off" if they aren't within amount distance of an existing "off" cell. This uses 8-way adjacency, and will never add "on" cells to the Region (it can only remove them or leave them as-is). This method acts like fringe8way(int) but only produces "on" cells where there were "on" cells at the edge of this Region's existing "on" cells.
      This operates in bulk on up to 64 cells at a time. This overload of surface8way allows taking a temp and temp2 Region that should be the same size as this Region, and won't allocate by modifying temp and temp2 in-place. While temp, if non-null, will reliably contain the same contents as this Region before this method call, temp2 won't have any guarantee. All values in temp2 will be eliminated, so it really should be considered temporary. If temp or temp2 is a different size from this Region, some memory will be allocated; allocation will also occur if any of temp or temp2 is null.
      Parameters:
      amount - how thick the bordering area should be
      temp - another Region that will be erased and replaced with the contents of this Region before this call; should be the same size as this
      temp2 - another Region that will be erased and replaced with undefined contents; should be the same size as this
      Returns:
      this for chaining
    • surfaceSeries8way

      public Region[] surfaceSeries8way(int amount)
      Takes the "on" cells in this Region and produces amount Regions, each one a smaller and smaller result of surface8way() by 1 cell in the 8 orthogonal and diagonal directions relative to the previous Region. After producing the expansions, this removes the previous Region from the next Region in the array, making each "surface" in the series have 1 "thickness," which can be useful for finding which layer of surfacing a cell lies in. This returns an array of Regions with progressively smaller perimeters taken from the cells of this Region, and does not modify this Region.
      This operates in bulk on up to 64 cells at a time. This method allocates multiple copied Regions and returns most of them in an array.
      Returns:
      an array of new Regions, length == amount, where each one is a 1-depth fringe pushed further out from this
    • surfaceSeriesToLimit8way

      public com.github.tommyettinger.ds.ObjectList<Region> surfaceSeriesToLimit8way()
      Returns an ObjectList of progressively further-retracted copied surfaces of this Region. This works like retractSeriesToLimit8way(), but produces one more Region copy than that method, and only retains the changed surface of the just-retracted area. This uses 8-way adjacency.
      Returns:
      a new ObjectList of copies of this Region, each retracted more and more until only a surface is left, and with everything but the latest change removed from each copy
    • flood

      public Region flood(Region bounds)
      Like expand(), but limits expansion to the "on" cells of bounds. Expands in all 4-way directions by one cell simultaneously, and only successfully affects the cells that are adjacent to this and are in bounds.
      Parameters:
      bounds - the set of "on" cells that limits where this can expand into
      Returns:
      this, after expanding, for chaining
    • flood

      public Region flood(Region bounds, Region buffer)
      Like expand(), but limits expansion to the "on" cells of bounds. Expands in all 4-way directions by one cell simultaneously, and only successfully affects the cells that are adjacent to this and are in bounds.
      This overload takes a buffer Region that should be the same size as this one. If it is, this won't allocate, and after the call, buffer will contain the previous contents of this Region.
      Parameters:
      bounds - the set of "on" cells that limits where this can expand into
      buffer - another Region that will be erased and replaced with the contents of this Region before this call; should be the same size as this
      Returns:
      this, after expanding, for chaining
    • flood

      public Region flood(Region bounds, int amount)
      Like expand(int), but limits expansion to the "on" cells of bounds. Repeatedly expands in the 4-way directions by one cell simultaneously, and only successfully affects the cells that are adjacent to the previous expansion and are in bounds. This won't skip over gaps in bounds, even if amount is high enough that a call to expand(int) would reach past the gap; it will stop at the gap and only pass it if expansion takes it around.
      Parameters:
      bounds - the set of "on" cells that limits where this can expand into
      amount - how far to expand this outward by, in cells
      Returns:
      this, after expanding, for chaining
    • flood

      public Region flood(Region bounds, int amount, Region buffer)
      Like expand(int), but limits expansion to the "on" cells of bounds. Repeatedly expands in all orthogonal directions by one cell simultaneously, and only successfully affects the cells that are adjacent to the previous expansion and are in bounds. This won't skip over gaps in bounds, even if amount is high enough that a call to expand(int) would reach past the gap; it will stop at the gap and only pass it if expansion takes it around.
      This overload takes a buffer Region that should be the same size as this one. If it is, this won't allocate. After the call, the contents of buffer will be undefined.
      Parameters:
      bounds - the set of "on" cells that limits where this can expand into
      amount - how far to expand this outward by, in cells
      buffer - another Region that will be erased and replaced with the contents of this Region before this call; should be the same size as this
      Returns:
      this, after expanding, for chaining
    • floodSeries

      public Region[] floodSeries(Region bounds, int amount)
      Repeatedly calls flood(Region) amount times and returns the intermediate steps in a Region array of size amount. Doesn't modify this Region, and doesn't return it in the array (it may return a copy of it if and only if no flood8way() calls can expand the area). If this fills bounds as fully as possible and still has steps left, the remaining steps are all copies of the fully-filled area.
      Parameters:
      bounds - the set of "on" cells that this will attempt to fill in steps
      amount - how many steps to flood outward, and the size of the array to return
      Returns:
      an array of Region, amount in size, containing larger and larger expansions of this
    • floodSeriesToLimit

      public com.github.tommyettinger.ds.ObjectList<Region> floodSeriesToLimit(Region bounds)
      Repeatedly generates new Regions, each one cell expanded in 4 directions from the previous Region and staying inside the "on" cells of bounds, until it can't expand any more. Returns an ObjectList of the Region steps this generated; this list does not include this Region (or any unmodified copy of this Region), and this method does not modify it.
      Parameters:
      bounds - the set of "on" cells that this will attempt to fill in steps
      Returns:
      an ObjectList of steps from one flood(Region) call to possibly many chained after it
    • flood8way

      public Region flood8way(Region bounds)
      Like expand8way(), but limits expansion to the "on" cells of bounds. Expands in all directions by one cell simultaneously, and only successfully affects the cells that are adjacent to this and are in bounds.
      Parameters:
      bounds - the set of "on" cells that limits where this can expand into
      Returns:
      this, after expanding, for chaining
    • flood8way

      public Region flood8way(Region bounds, Region buffer)
      Like expand8way(), but limits expansion to the "on" cells of bounds. Expands in all directions by one cell simultaneously, and only successfully affects the cells that are adjacent to this and are in bounds.
      This overload takes a buffer Region that should be the same size as this one. If it is, this won't allocate, and after the call, buffer will contain the previous contents of this Region.
      Parameters:
      bounds - the set of "on" cells that limits where this can expand into
      buffer - another Region that will be erased and replaced with the contents of this Region before this call; should be the same size as this
      Returns:
      this, after expanding, for chaining
    • flood8way

      public Region flood8way(Region bounds, int amount)
      Like expand8way(int), but limits expansion to the "on" cells of bounds. Repeatedly expands in all directions by one cell simultaneously, and only successfully affects the cells that are adjacent to the previous expansion and are in bounds. This won't skip over gaps in bounds, even if amount is high enough that a call to expand8way(int) would reach past the gap; it will stop at the gap and only pass it if expansion takes it around.
      Parameters:
      bounds - the set of "on" cells that limits where this can expand into
      amount - how far to expand this outward by, in cells
      Returns:
      this, after expanding, for chaining
    • flood8way

      public Region flood8way(Region bounds, int amount, Region buffer)
      Like expand8way(int), but limits expansion to the "on" cells of bounds. Repeatedly expands in all directions by one cell simultaneously, and only successfully affects the cells that are adjacent to the previous expansion and are in bounds. This won't skip over gaps in bounds, even if amount is high enough that a call to expand8way(int) would reach past the gap; it will stop at the gap and only pass it if expansion takes it around.
      This overload takes a buffer Region that should be the same size as this one. If it is, this won't allocate. After the call, the contents of buffer will be undefined.
      Parameters:
      bounds - the set of "on" cells that limits where this can expand into
      amount - how far to expand this outward by, in cells
      buffer - another Region that will be erased and replaced with the contents of this Region before this call; should be the same size as this
      Returns:
      this, after expanding, for chaining
    • floodSeries8way

      public Region[] floodSeries8way(Region bounds, int amount)
      Repeatedly calls flood8way(Region) amount times and returns the intermediate steps in a Region array of size amount. Doesn't modify this Region, and doesn't return it in the array (it may return a copy of it if and only if no flood8way() calls can expand the area). If this fills bounds as fully as possible and still has steps left, the remaining steps are all copies of the fully-filled area.
      Parameters:
      bounds - the set of "on" cells that this will attempt to fill in steps
      amount - how many steps to flood outward, and the size of the array to return
      Returns:
      an array of Region, amount in size, containing larger and larger expansions of this
    • floodSeriesToLimit8way

      public com.github.tommyettinger.ds.ObjectList<Region> floodSeriesToLimit8way(Region bounds)
      Repeatedly generates new Regions, each one cell expanded in 8 directions from the previous Region and staying inside the "on" cells of bounds, until it can't expand anymore. Returns an ObjectList of the Region steps this generated; this list does not include this Region (or any unmodified copy of this Region), and this method does not modify it.
      Parameters:
      bounds - the set of "on" cells that this will attempt to fill in steps
      Returns:
      an ObjectList of steps from one flood8way(Region) call to possibly many chained after it
    • splash

      public Region splash(Region bounds, com.github.tommyettinger.random.EnhancedRandom rng)
      A randomized flood-fill that modifies this Region so it randomly adds one adjacent cell if it can while staying inside the "on" cells of bounds. This Region acts as the initial state, and often contains just one cell before this is called. This method is useful for imitating the movement of fluids like water or smoke within some boundaries, stepping one-cell-at-a-time instead of how spill(Region, int, EnhancedRandom) fills a whole volume.
      This overload allocates a Region used by splash(Region, EnhancedRandom, Region).
      Parameters:
      bounds - this Region will only expand to a cell that is "on" in bounds; bounds should overlap with this
      rng - a EnhancedRandom, or a recommended subclass like WhiskerRandom
      Returns:
      this, after expanding randomly once, for chaining
    • splash

      public Region splash(Region bounds, com.github.tommyettinger.random.EnhancedRandom rng, Region temp)
      A randomized flood-fill that modifies this Region so it randomly adds one adjacent cell if it can while staying inside the "on" cells of bounds. This Region acts as the initial state, and often contains just one cell before this is called. This method is useful for imitating the movement of fluids like water or smoke within some boundaries, stepping one-cell-at-a-time instead of how spill(Region, int, EnhancedRandom) fills a whole volume.
      This overload is just like the one that doesn't take a temp Region, but it can avoid allocating a new Region if you have one with the same size as this, to use as working space.
      Parameters:
      bounds - this Region will only expand to a cell that is "on" in bounds; bounds should overlap with this
      rng - a EnhancedRandom, or a recommended subclass like WhiskerRandom
      temp - another Region that will be cleared and used as a temporary buffer; optimally the same size as this
      Returns:
      this, after expanding randomly once, for chaining
    • spill

      public Region spill(Region bounds, int volume, com.github.tommyettinger.random.EnhancedRandom rng)
      A randomized flood-fill that modifies this Region so it randomly adds adjacent cells while staying inside the "on" cells of bounds, until size() is equal to volume or there are no more cells this can expand into. This Region acts as the initial state, and often contains just one cell before this is called. This method is useful for imitating the movement of fluids like water or smoke within some boundaries.
      This method allocates two temporary Regions used by spill(Region, int, EnhancedRandom, Region, Region).
      Parameters:
      bounds - this Region will only expand to cells that are "on" in bounds; bounds should overlap with this
      volume - the maximum size() this Region can reach before this stops expanding
      rng - a EnhancedRandom, or a recommended subclass like WhiskerRandom
      Returns:
      this, after expanding randomly, for chaining
    • spill

      public Region spill(Region bounds, int volume, com.github.tommyettinger.random.EnhancedRandom rng, Region temp, Region temp2)
      A randomized flood-fill that modifies this Region so it randomly adds adjacent cells while staying inside the "on" cells of bounds, until size() is equal to volume or there are no more cells this can expand into. This Region acts as the initial state, and often contains just one cell before this is called. This method is useful for imitating the movement of fluids like water or smoke within some boundaries.
      This overload is just like the one that doesn't take a temp Region, but it can avoid allocating new Regions if you have two with the same size as this, to use as working space.
      Parameters:
      bounds - this Region will only expand to cells that are "on" in bounds; bounds should overlap with this
      volume - the maximum size() this Region can reach before this stops expanding
      rng - a EnhancedRandom, or a recommended subclass like WhiskerRandom
      temp - another Region that will be cleared and used as a temporary buffer; optimally the same size as this
      temp2 - another Region that will be cleared and used as a temporary buffer; optimally the same size as this
      Returns:
      this, after expanding randomly, for chaining
    • stir

      public Region stir(Region bounds, com.github.tommyettinger.function.IntIntPredicate decider)
      A selective flood-fill that modifies this Region so it adds adjacent cells that decider evaluates to true for, if it can while staying inside the "on" cells of bounds. This Region acts as the initial state, and often contains just one cell before this is called. This method is useful for imitating the movement of fluids like water or smoke within some boundaries, stepping only to adjacent cells instead of how spill(Region, int, EnhancedRandom) fills a whole volume, or how splash(Region, EnhancedRandom) only steps to one random cell. The decider is often a lambda that calls an INoise type's 2D or 3D noise methods and compares to a threshold. If using 3D noise, changing z between calls will usually allow all cells to eventually be reached, but this can't be guaranteed, especially for extreme thresholds.
      This only calls the decider's IntIntPredicate.test(int, int) method on cells adjacent to "on" cells in this that are also within bounds.
      This overload allocates a Region used by stir(Region, IntIntPredicate, Region).
      Parameters:
      bounds - this Region will only expand to a cell that is "on" in bounds; bounds should overlap with this
      decider - a function that takes two ints (x, y) and returns true if that position should be kept
      Returns:
      this, after expanding to adjacent cells where decider returned true, for chaining
    • stir

      public Region stir(Region bounds, com.github.tommyettinger.function.IntIntPredicate decider, Region temp)
      A selective flood-fill that modifies this Region so it adds adjacent cells that decider evaluates to true for, if it can while staying inside the "on" cells of bounds. This Region acts as the initial state, and often contains just one cell before this is called. This method is useful for imitating the movement of fluids like water or smoke within some boundaries, stepping only to adjacent cells instead of how spill(Region, int, EnhancedRandom) fills a whole volume, or how splash(Region, EnhancedRandom) only steps to one random cell. The decider is often a lambda that calls an INoise type's 2D or 3D noise methods and compares to a threshold. If using 3D noise, changing z between calls will usually allow all cells to eventually be reached, but this can't be guaranteed, especially for extreme thresholds.
      This only calls the decider's IntIntPredicate.test(int, int) method on cells adjacent to "on" cells in this that are also within bounds.
      This overload is just like the one that doesn't take a temp Region, but it can avoid allocating a new Region if you have one with the same size as this, to use as working space.
      Parameters:
      bounds - this Region will only expand to a cell that is "on" in bounds; bounds should overlap with this
      decider - a function that takes two ints (x, y) and returns true if that position should be kept
      temp - another Region that will be cleared and used as a temporary buffer; optimally the same size as this
      Returns:
      this, after expanding to adjacent cells where decider returned true, for chaining
    • stir

      public Region stir(Region bounds, INoise noise, float lowerBound, float upperBound)
      A selective flood-fill that modifies this Region so it adds adjacent cells where noise.getNoise(x, y) evaluates between lowerBound (inclusive) and upperBound (exclusive), if it can while staying inside the "on" cells of bounds. This Region acts as the initial state, and often contains just one cell before this is called. This method is useful for imitating the movement of fluids like water or smoke within some boundaries, stepping only to adjacent cells instead of how spill(Region, int, EnhancedRandom) fills a whole volume, or how splash(Region, EnhancedRandom) only steps to one random cell. Because this requests 2D noise, unless the noise has its seed change between calls (making each call totally and randomly different), some areas will usually not be possible to fill with typical bounds (ones that don't just accept all noise as in-bounds). The result from each call to getNoise() should be between -1.0 and 1.0, so both bounds are typically in that range or just outside it (to allow all low values or all high values).
      This only calls noise's INoise.getNoise(float, float) method on cells adjacent to "on" cells in this that are also within bounds.
      This overload allocates a Region used by stir(Region, IntIntPredicate, Region).
      Parameters:
      bounds - this Region will only expand to a cell that is "on" in bounds; bounds should overlap with this
      noise - an INoise that will have its INoise.getNoise(float, float) method called per adjacent cell
      lowerBound - usually between -1 and 1; if a result from noise at a cell is less than lowerBound, that cell won't be added
      upperBound - usually between -1 and 1; if a result from noise at a cell is greater than or equal to upperBound, that cell won't be added
      Returns:
      this, after expanding to adjacent cells where the noise was within range, for chaining
    • stir

      public Region stir(Region bounds, INoise noise, float lowerBound, float upperBound, Region temp)
      A selective flood-fill that modifies this Region so it adds adjacent cells where noise.getNoise(x, y) evaluates between lowerBound (inclusive) and upperBound (exclusive), if it can while staying inside the "on" cells of bounds. This Region acts as the initial state, and often contains just one cell before this is called. This method is useful for imitating the movement of fluids like water or smoke within some boundaries, stepping only to adjacent cells instead of how spill(Region, int, EnhancedRandom) fills a whole volume, or how splash(Region, EnhancedRandom) only steps to one random cell. Because this requests 2D noise, unless the noise has its seed change between calls (making each call totally and randomly different), some areas will usually not be possible to fill with typical bounds (ones that don't just accept all noise as in-bounds). The result from each call to getNoise() should be between -1.0 and 1.0, so both bounds are typically in that range or just outside it (to allow all low values or all high values).
      This only calls noise's INoise.getNoise(float, float) method on cells adjacent to "on" cells in this that are also within bounds.
      This overload is just like the one that doesn't take a temp Region, but it can avoid allocating a new Region if you have one with the same size as this, to use as working space.
      Parameters:
      bounds - this Region will only expand to a cell that is "on" in bounds; bounds should overlap with this
      noise - an INoise that will have its INoise.getNoise(float, float) method called per adjacent cell
      lowerBound - usually between -1 and 1; if a result from noise at a cell is less than lowerBound, that cell won't be added
      upperBound - usually between -1 and 1; if a result from noise at a cell is greater than or equal to upperBound, that cell won't be added
      temp - another Region that will be cleared and used as a temporary buffer; optimally the same size as this
      Returns:
      this, after expanding to adjacent cells where the noise was within range, for chaining
    • stir

      public Region stir(Region bounds, INoise noise, float z, float lowerBound, float upperBound)
      A selective flood-fill that modifies this Region so it adds adjacent cells where noise.getNoise(x, y, z) evaluates between lowerBound (inclusive) and upperBound (exclusive), if it can while staying inside the "on" cells of bounds. This allows specifying the z parameter here. This Region acts as the initial state, and often contains just one cell before this is called. This method is useful for imitating the movement of fluids like water or smoke within some boundaries, stepping only to adjacent cells instead of how spill(Region, int, EnhancedRandom) fills a whole volume, or how splash(Region, EnhancedRandom) only steps to one random cell. This requests 3D noise from noise, and the z parameter can change between calls; this can allow the noise to gradually change over multiple calls or multiple frames, which could allow spaces that previously couldn't be filled to become fillable. The result from each call to getNoise() should be between -1.0 and 1.0, so both bounds are typically in that range or just outside it (to allow all low values or all high values).
      This only calls noise's INoise.getNoise(float, float, float) method on cells adjacent to "on" cells in this that are also within bounds.
      This overload allocates a Region used by stir(Region, IntIntPredicate, Region).
      Parameters:
      bounds - this Region will only expand to a cell that is "on" in bounds; bounds should overlap with this
      noise - an INoise that will have its INoise.getNoise(float, float, float) method called per adjacent cell
      z - the third parameter to be passed to getNoise()
      lowerBound - usually between -1 and 1; if a result from noise at a cell is less than lowerBound, that cell won't be added
      upperBound - usually between -1 and 1; if a result from noise at a cell is greater than or equal to upperBound, that cell won't be added
      Returns:
      this, after expanding to adjacent cells where the noise was within range, for chaining
    • stir

      public Region stir(Region bounds, INoise noise, float z, float lowerBound, float upperBound, Region temp)
      A selective flood-fill that modifies this Region so it adds adjacent cells where noise.getNoise(x, y, z) evaluates between lowerBound (inclusive) and upperBound (exclusive), if it can while staying inside the "on" cells of bounds. This allows specifying the z parameter here. This Region acts as the initial state, and often contains just one cell before this is called. This method is useful for imitating the movement of fluids like water or smoke within some boundaries, stepping only to adjacent cells instead of how spill(Region, int, EnhancedRandom) fills a whole volume, or how splash(Region, EnhancedRandom) only steps to one random cell. This requests 3D noise from noise, and the z parameter can change between calls; this can allow the noise to gradually change over multiple calls or multiple frames, which could allow spaces that previously couldn't be filled to become fillable. The result from each call to getNoise() should be between -1.0 and 1.0, so both bounds are typically in that range or just outside it (to allow all low values or all high values).
      This only calls noise's INoise.getNoise(float, float, float) method on cells adjacent to "on" cells in this that are also within bounds.
      This overload is just like the one that doesn't take a temp Region, but it can avoid allocating a new Region if you have one with the same size as this, to use as working space.
      Parameters:
      bounds - this Region will only expand to a cell that is "on" in bounds; bounds should overlap with this
      noise - an INoise that will have its INoise.getNoise(float, float, float) method called per adjacent cell
      z - the third parameter to be passed to getNoise()
      lowerBound - usually between -1 and 1; if a result from noise at a cell is less than lowerBound, that cell won't be added
      upperBound - usually between -1 and 1; if a result from noise at a cell is greater than or equal to upperBound, that cell won't be added
      temp - another Region that will be cleared and used as a temporary buffer; optimally the same size as this
      Returns:
      this, after expanding to adjacent cells where the noise was within range, for chaining
    • removeCorners

      public Region removeCorners()
      Where a cell is "on" but forms a right-angle with exactly two orthogonally-adjacent "on" cells and exactly two orthogonally-adjacent "off" cells, this turns each of those cells "off." This won't affect east-west lines of flat "on" cells, nor north-south lines.
      Returns:
      this, after removing right-angle corner "on" cells, for chaining
    • removeCorners

      public Region removeCorners(Region buffer)
      Where a cell is "on" but forms a right-angle with exactly two orthogonally-adjacent "on" cells and exactly two orthogonally-adjacent "off" cells, this turns each of those cells "off." This won't affect east-west lines of flat "on" cells, nor north-south lines.
      Returns:
      this, after removing right-angle corner "on" cells, for chaining
    • split

      public com.github.tommyettinger.ds.ObjectList<Region> split()
      If this Region stores multiple unconnected "on" areas, this finds each isolated area (areas that are only adjacent diagonally are considered separate from each other) and returns it as an element in an ObjectList of Region, with one Region per isolated area. Not to be confused with split8way(), which considers diagonally-adjacent cells as part of one region, while this method requires cells to be orthogonally adjacent.
      Useful when you have, for example, all the rooms in a dungeon with their connecting corridors removed, but want to separate the rooms. You can get the aforementioned data assuming a bare dungeon called map using:
      Region floors = new Region(map, '.'), rooms = floors.copy().retract8way().flood(floors, 2), corridors = floors.copy().andNot(rooms), doors = rooms.copy().and(corridors.copy().fringe());
      You can then get all rooms as separate regions with List<Region> apart = split(rooms);, or substitute split(corridors) to get the corridors. The room-finding technique works by shrinking floors by a radius of 1 (8-way), which causes thin areas like corridors of 2 or less width to be removed, then flood-filling the floors out from the area that produces by 2 cells (4-way this time) to restore the original size of non-corridor areas (plus some extra to ensure odd shapes are kept). Corridors are obtained by removing the rooms from floors. The example code also gets the doors (which overlap with rooms, not corridors) by finding where a room and a corridor are adjacent. This technique is used with some enhancements in the RoomFinder class.
      Returns:
      an ObjectList containing each unconnected area from packed as a Region element
    • split8way

      public com.github.tommyettinger.ds.ObjectList<Region> split8way()
      If this Region stores multiple unconnected "on" areas, this finds each isolated area (areas that are only adjacent diagonally are considered one area with this) and returns it as an element in an ObjectList of Region, with one Region per isolated area. This should not be confused with split(), which is almost identical except that split() considers only orthogonal connections, while this method considers both orthogonal and diagonal connections between cells as joining an area.
      Useful when you have, for example, all the rooms in a dungeon with their connecting corridors removed, but want to separate the rooms. You can get the aforementioned data assuming a bare dungeon called map using:
      Region floors = new Region(map, '.'), rooms = floors.copy().retract8way().flood(floors, 2), corridors = floors.copy().andNot(rooms), doors = rooms.copy().and(corridors.copy().fringe());
      You can then get all rooms as separate regions with List<Region> apart = split(rooms);, or substitute split(corridors) to get the corridors. The room-finding technique works by shrinking floors by a radius of 1 (8-way), which causes thin areas like corridors of 2 or less width to be removed, then flood-filling the floors out from the area that produces by 2 cells (4-way this time) to restore the original size of non-corridor areas (plus some extra to ensure odd shapes are kept). Corridors are obtained by removing the rooms from floors. The example code also gets the doors (which overlap with rooms, not corridors) by finding where a room and a corridor are adjacent. This technique is used with some enhancements in the RoomFinder class.
      Returns:
      an ObjectList containing each unconnected area from packed as a Region element
    • largestPart

      public Region largestPart()
      Finds the largest contiguous area of "on" cells in this Region and returns it; does not modify this Region. If there are multiple areas that are all equally large with no larger area, this returns the region it checks first and still is largest (first determined by the same ordering nth(int) takes). This may return an empty Region if there are no "on" cells, but it will never return null. Here, contiguous means adjacent on an orthogonal direction, and this doesn't consider diagonally-connected cells as contiguous unless they also have an orthogonal connection.
      Returns:
      a new Region that corresponds to the largest contiguous sub-region of "on" cells in this.
    • largestPart8way

      public Region largestPart8way()
      Finds the largest contiguous area of "on" cells in this Region and returns it; does not modify this Region. If there are multiple areas that are all equally large with no larger area, this returns the region it checks first and still is largest (first determined by the same ordering nth(int) takes). This may return an empty Region if there are no "on" cells, but it will never return null. Here, contiguous means adjacent on any 8-way direction, and considers cells as part of a contiguous area even if all connections but one, which can be orthogonal or diagonal, are blocked by "off" cells.
      Returns:
      a new Region that corresponds to the largest contiguous sub-region of "on" cells in this.
    • neighborUp

      public Region neighborUp()
      Modifies this Region so the only cells that will be "on" have a neighbor upwards when this is called. Up is defined as negative y. Neighbors are "on" cells exactly one cell away. A cell can have a neighbor without itself being on; this is useful when finding the "shadow" cast away from "on" cells in one direction.
      Returns:
      this, after modifications, for chaining
    • neighborDown

      public Region neighborDown()
      Modifies this Region so the only cells that will be "on" have a neighbor downwards when this is called. Down is defined as positive y. Neighbors are "on" cells exactly one cell away. A cell can have a neighbor without itself being on; this is useful when finding the "shadow" cast away from "on" cells in one direction.
      Returns:
      this, after modifications, for chaining
    • neighborLeft

      public Region neighborLeft()
      Modifies this Region so the only cells that will be "on" have a neighbor to the left when this is called. Left is defined as negative x. Neighbors are "on" cells exactly one cell away. A cell can have a neighbor without itself being on; this is useful when finding the "shadow" cast away from "on" cells in one direction.
      Returns:
      this, after modifications, for chaining
    • neighborRight

      public Region neighborRight()
      Modifies this Region so the only cells that will be "on" have a neighbor to the right when this is called. Right is defined as positive x. Neighbors are "on" cells exactly one cell away. A cell can have a neighbor without itself being on; this is useful when finding the "shadow" cast away from "on" cells in one direction.
      Returns:
      this, after modifications, for chaining
    • neighborUpLeft

      public Region neighborUpLeft()
      Modifies this Region so the only cells that will be "on" have a neighbor upwards and to the left when this is called. Up is defined as negative y, left as negative x. Neighbors are "on" cells exactly one cell away. A cell can have a neighbor without itself being on; this is useful when finding the "shadow" cast away from "on" cells in one direction.
      Returns:
      this, after modifications, for chaining
    • neighborUpRight

      public Region neighborUpRight()
      Modifies this Region so the only cells that will be "on" have a neighbor upwards and to the right when this is called. Up is defined as negative y, right as positive x. Neighbors are "on" cells exactly one cell away. A cell can have a neighbor without itself being on; this is useful when finding the "shadow" cast away from "on" cells in one direction.
      Returns:
      this, after modifications, for chaining
    • neighborDownLeft

      public Region neighborDownLeft()
      Modifies this Region so the only cells that will be "on" have a neighbor downwards and to the left when this is called. Down is defined as positive y, left as negative x. Neighbors are "on" cells exactly one cell away. A cell can have a neighbor without itself being on; this is useful when finding the "shadow" cast away from "on" cells in one direction.
      Returns:
      this, after modifications, for chaining
    • neighborDownRight

      public Region neighborDownRight()
      Modifies this Region so the only cells that will be "on" have a neighbor downwards and to the right when this is called. Down is defined as positive y, right as positive x. Neighbors are "on" cells exactly one cell away. A cell can have a neighbor without itself being on; this is useful when finding the "shadow" cast away from "on" cells in one direction.
      Returns:
      this, after modifications, for chaining
    • removeIsolated

      public Region removeIsolated()
    • intersects

      public boolean intersects(Region other)
      Returns true if any cell is "on" in both this Region and in other; returns false otherwise. For example, if (1,1) is "on" in this and (1,1) is "on" in other, this would return true, regardless of other cells.
      Parameters:
      other - another Region; its size does not have to match this Region's size
      Returns:
      true if this shares any "on" cells with other
    • whichContain

      public static com.github.tommyettinger.ds.ObjectOrderedSet<Region> whichContain(int x, int y, Region... packed)
    • whichContain

      public static com.github.tommyettinger.ds.ObjectOrderedSet<Region> whichContain(int x, int y, Collection<Region> packed)
    • appendContaining

      public static Collection<Region> appendContaining(Collection<Region> into, int x, int y, Region... packed)
      Tries to look up the position x,y in each Region in packed; each Region that contains that x,y point is appended into the Collection into.
      Parameters:
      into - a Collection of Region that will be modified if this succeeds
      x - the x-coordinate to look up
      y - the y-coordinate to look up
      packed - the array or varargs of Region to try to look up the given position in
      Returns:
      into, potentially modified
    • appendContaining

      public static Collection<Region> appendContaining(Collection<Region> into, int x, int y, Collection<Region> packed)
      Tries to look up the position x,y in each Region in packed; each Region that contains that x,y point is appended into the Collection into.
      Parameters:
      into - a Collection of Region that will be modified if this succeeds
      x - the x-coordinate to look up
      y - the y-coordinate to look up
      packed - the Collection of Region to try to look up the given position in
      Returns:
      into, potentially modified
    • size

      public int size()
      Specified by:
      size in interface Collection<Coord>
    • fit

      public Coord fit(float xFraction, float yFraction)
    • fit

      public int[][] fit(int[][] basis, int defaultValue)
    • fray

      public Region fray(float fractionKept)
      Like retract(), this removes the "on" cells that are 4-way-adjacent to any "off" cell, but unlike that method it keeps a fraction of those surface cells, quasi-randomly selecting them. This can be thought of as running surface() on a copy of this Region, running separatedRegionBlue(float) on that surface with the given fractionKept, taking the original Region and removing its whole surface with retract(), then inserting the quasi-randomly-removed surface into this Region to replace its surface with a randomly "damaged" one.
      Parameters:
      fractionKept - the fraction between 0.0 and 1.0 of how many cells on the outer surface of this to keep "on"
      Returns:
      this for chaining
    • fray

      public Region fray(float fractionKept, Region buffer)
      Like retract(), this removes the "on" cells that are 4-way-adjacent to any "off" cell, but unlike that method it keeps a fraction of those surface cells, quasi-randomly selecting them. This can be thought of as running surface() on a copy of this Region, running separatedRegionBlue(float) on that surface with the given fractionKept, taking the original Region and removing its whole surface with retract(), then inserting the quasi-randomly-removed surface into this Region to replace its surface with a randomly "damaged" one.
      This overload takes a buffer Region that should be the same size as this one. If it is, this won't allocate. After the call, the contents of buffer will be the same as a copy of this with retract() called once.
      Parameters:
      fractionKept - the fraction between 0.0 and 1.0 of how many cells on the outer surface of this to keep "on"
      buffer - another Region that will be erased and replaced with the contents of this Region before this call; should be the same size as this
      Returns:
      this for chaining
    • fray

      public Region fray(com.github.tommyettinger.random.EnhancedRandom random, float fractionKept)
      Like retract(), this removes the "on" cells that are 4-way-adjacent to any "off" cell, but unlike that method it keeps a fraction of those surface cells, randomly selecting them. This can be thought of as running surface() on a copy of this Region, running deteriorate(EnhancedRandom, float) on that surface with the given fractionKept, taking the original Region and removing its whole surface with retract(), then inserting the randomly-removed surface into this Region to replace its surface with a randomly "damaged" one.
      Parameters:
      random - a EnhancedRandom, or a recommended subclass like WhiskerRandom
      fractionKept - the fraction between 0.0 and 1.0 of how many cells on the outer surface of this to keep "on"
      Returns:
      this for chaining
    • fray

      public Region fray(com.github.tommyettinger.random.EnhancedRandom random, float fractionKept, Region buffer)
      Like retract(), this removes the "on" cells that are 4-way-adjacent to any "off" cell, but unlike that method it keeps a fraction of those surface cells, randomly selecting them. This can be thought of as running surface() on a copy of this Region, running deteriorate(EnhancedRandom, float) on that surface with the given fractionKept, taking the original Region and removing its whole surface with retract(), then inserting the randomly-removed surface into this Region to replace its surface with a randomly "damaged" one.
      This overload takes a buffer Region that should be the same size as this one. If it is, this won't allocate. After the call, the contents of buffer will be the same as a copy of this with retract() called once.
      Parameters:
      random - a EnhancedRandom, or a recommended subclass like WhiskerRandom
      fractionKept - the fraction between 0.0 and 1.0 of how many cells on the outer surface of this to keep "on"
      buffer - another Region that will be erased and replaced with the contents of this Region before this call; should be the same size as this
      Returns:
      this for chaining
    • randomScatter

      public Region randomScatter(com.github.tommyettinger.random.EnhancedRandom rng, int minimumDistance)
      Modifies this Region so it contains a random subset of its previous contents, choosing cells so that the distance between any two "on" cells is at least minimumDistance, with at least one cell as "on" if any were "on" in this originally. Does not limit the count of "on" cells in the result.
      Parameters:
      rng - a EnhancedRandom, or a recommended subclass like WhiskerRandom
      minimumDistance - the minimum distance between "on" cells in the result
      Returns:
      this for chaining
    • randomScatter

      public Region randomScatter(com.github.tommyettinger.random.EnhancedRandom rng, int minimumDistance, int limit)
      Modifies this Region so it contains a random subset of its previous contents, choosing cells so that the distance between any two "on" cells is at least minimumDistance, with at least one cell as "on" if any were "on" in this originally. Restricts the total count of "on" cells after this returns to a maximum of limit (minimum is 0 if no cells are "on"). If limit is negative, this will not restrict the count.
      Parameters:
      rng - a EnhancedRandom, or a recommended subclass like WhiskerRandom
      minimumDistance - the minimum distance between "on" cells in the result
      limit - the maximum count of "on" cells to keep
      Returns:
      this for chaining
    • rateDensity

      public float rateDensity()
    • rateRegularity

      public float rateRegularity()
    • perceptualHashQuick

      public void perceptualHashQuick(long[] into, int[] working)
      Calculates a perceptual hash for this Region using a method that is only precise for some sizes of Region; it writes a result to into, and uses working as a temporary buffer. The lengths of into and working should be related; if into is length 1, then working should be length 64, and though the hash won't be very detailed, it will work well for images with width and height that are multiples of 8; if into is length 4, then working should be length 256, and this will work with more detail on images that have width and height that are multiples of 16. If working is null or is too small, then this won't reuse it and will allocate an appropriately-sized array for internal use.
      Ported from blockhash by commonsmachinery, which is MIT-licensed.
      Parameters:
      into - should be a long array of length 1 or 4; the contents don't matter and this will be where output is written to
      working - should be an int array of length 64 (if into has length 1) or 256 (if into has length 4); may be null if you like garbage collection
    • asCoords

      public Coord[] asCoords()
    • asCoords

      public Coord[] asCoords(Coord[] points)
    • asEncoded

      public int[] asEncoded()
    • asTightEncoded

      public int[] asTightEncoded()
    • first

      public Coord first()
      Gets the first Coord in the iteration order, or (-1,-1) if this Region is empty.
      Returns:
      the first Coord in the iteration order, or (-1,-1) if this Region is empty
    • firstTight

      public int firstTight()
    • last

      public Coord last()
      Gets the last Coord in the iteration order, or (-1,-1) if this Region is empty.
      Returns:
      the last Coord in the iteration order, or (-1,-1) if this Region is empty
    • lastTight

      public int lastTight()
    • nth

      public Coord nth(int index)
    • atFraction

      public Coord atFraction(float fraction)
    • atFractionTight

      public int atFractionTight(float fraction)
    • singleRandom

      public Coord singleRandom(com.github.tommyettinger.random.EnhancedRandom rng)
      Gets a single random Coord from the "on" positions in this Region, or the Coord (-1,-1) if this is empty. Uses the given EnhancedRandom to generate one random int, which is used as an index. The technique this uses to iterate over bits can be credited to Erling Ellingsen and Daniel Lemire, found here, and seems to be a little faster than the previous method. The fastest way to get a random Coord from a Region is to avoid iterating over the bits at all, so if your region data doesn't change you should get it as a Coord array with asCoords() and call EnhancedRandom.nextInt(int) to get an index inside that Coord array. If you take the asCoords() call out of consideration, getting random elements out of an array (especially a large one) can be hundreds of times faster.
      Parameters:
      rng - a EnhancedRandom, or a recommended subclass like WhiskerRandom
      Returns:
      a single randomly-chosen Coord from the "on" positions in this Region, or (-1,-1) if empty
    • singleRandomTight

      public int singleRandomTight(com.github.tommyettinger.random.EnhancedRandom rng)
    • interleaveBits

      public static int interleaveBits(int x, int y)
      Narrow-purpose; takes an x and a y value, each between 0 and 65535 inclusive, and interleaves their bits so the least significant bit and every other bit after it are filled with the bits of x, while the second-least-significant bit and every other bit after that are filled with the bits of y. Essentially, this takes two numbers with bits labeled like a b c for x and R S T for y and makes a number with those bits arranged like R a S b T c. Numbers made by interleaving other numbers like this are sometimes called Morton codes, and the sequence of Morton codes forms a pattern called the Z-order curve.
      Parameters:
      x - an int between 0 and 65535, inclusive
      y - an int between 0 and 65535, inclusive
      Returns:
      an int that interleaves x and y, with x in the least significant bit position
    • disperseBits

      public static int disperseBits(int n)
      Narrow-purpose; takes an int that represents a distance down the Z-order curve and moves its bits around so that its x component is stored in the bottom 16 bits (use (n & 0xffff) to obtain) and its y component is stored in the upper 16 bits (use (n >>> 16) to obtain). This may be useful for ordering traversals of all points in a Region less predictably. Numbers made by interleaving other numbers, like n, are sometimes called Morton codes, and the sequence of Morton codes forms a pattern called the Z-order curve.
      Parameters:
      n - an int that has already been interleaved, though this can really be any int
      Returns:
      an int with x in its lower bits (x = n & 0xffff;) and y in its upper bits (y = n >>> 16;)
    • separatedBlue

      public Coord[] separatedBlue(float fraction)
      Gets a Coord array from the "on" contents of this Region, using a quasi-random scattering of chosen cells with a count that matches the given fraction of the total amount of "on" cells in this. This is quasi- random instead of pseudo-random because it uses blue noise to sharply limit the likelihood of nearby points being chosen when fraction is small. If you request too many cells (too high of a value for fraction), it will start to have nearby cells, however. Does not restrict the size of the returned array other than only using up to fraction * size() cells.
      Internally, this is a thin wrapper around separatedRegionBlue(float, int), and won't be more efficient than that method.
      Parameters:
      fraction - the fraction of "on" cells to randomly select, between 0.0 and 1.0
      Returns:
      a freshly-allocated Coord array containing the quasi-random cells
    • separatedBlue

      public Coord[] separatedBlue(float fraction, int limit)
      Gets a Coord array from the "on" contents of this Region, using a quasi-random scattering of chosen cells with a count that matches the given fraction of the total amount of "on" cells in this. This is quasi- random instead of pseudo-random because it uses blue noise to sharply limit the likelihood of nearby points being chosen when fraction is small. If you request too many cells (too high of a value for fraction), it will start to have nearby cells, however. Restricts the total size of the returned array to a maximum of limit (minimum is 0 if no cells are "on"). If limit is negative, this will not restrict the size.
      Internally, this is a thin wrapper around separatedRegionBlue(float, int), and won't be more efficient than that method.
      Parameters:
      fraction - the fraction of "on" cells to randomly select, between 0.0 and 1.0
      limit - the maximum size of the array to return; may return less
      Returns:
      a freshly-allocated Coord array containing the quasi-random cells
    • separatedRegionBlue

      public Region separatedRegionBlue(float fraction)
      Modifies this Region so it contains a quasi-random subset of its previous contents, choosing cells so that the size() matches the given fraction of the total amount of "on" cells in this. This is quasi- random instead of pseudo-random because it uses blue noise to sharply limit the likelihood of nearby points being chosen when fraction is small. If you request too many cells (too high of a value for fraction), it will start to have nearby cells, however. Does not restrict the size of the returned Region other than only using up to fraction * size() cells.
      Parameters:
      fraction - the fraction of "on" cells to randomly select, between 0.0 and 1.0
      Returns:
      this, after modifications, for chaining
    • separatedRegionBlue

      public Region separatedRegionBlue(float fraction, int limit)
      Modifies this Region so it contains a quasi-random subset of its previous contents, choosing cells so that the size() matches the given fraction of the total amount of "on" cells in this. This is quasi- random instead of pseudo-random because it uses blue noise to sharply limit the likelihood of nearby points being chosen when fraction is small. If you request too many cells (too high of a value for fraction), it will start to have nearby cells, however. Restricts the total size of the returned Region to a maximum of limit (minimum is 0 if no cells are "on"). If limit is negative, this will not restrict the size.
      Parameters:
      fraction - the fraction of "on" cells to quasi-randomly select, between 0.0 and 1.0
      limit - the maximum size of the Region to return; a negative number will make this have no limit
      Returns:
      this, after modifications, for chaining
    • separatedPoisson

      public Coord[] separatedPoisson(com.github.tommyettinger.random.EnhancedRandom rng, float minimumDistance)
      Gets all but a quasi-random group of "on" cells that each has at least minimumDistance between itself and any other cell in the returned array. Works on a copy of this Region, so this object won't be modified.
      Parameters:
      rng - an EnhancedRandom to randomly choose points; may be queried quite a lot for large Regions
      minimumDistance - the minimum distance between points to allow; this is a float, and distances will be rounded
      Returns:
      a new Coord array containing some of the "on" cells in this Region
    • separatedPoisson

      public Coord[] separatedPoisson(com.github.tommyettinger.random.EnhancedRandom rng, float minimumDistance, int limit)
      Gets all but a quasi-random group of "on" cells that each has at least minimumDistance between itself and any other cell in the returned array. Works on a copy of this Region, so this object won't be modified. This overload takes a limit; if limit is non-negative, it will be used as the maximum number of "on" cells to permit in the result. When there would otherwise be more "on" cells than the limit, this randomly chooses which ones to keep.
      Parameters:
      rng - an EnhancedRandom to randomly choose points; may be queried quite a lot for large Regions
      minimumDistance - the minimum distance between points to allow; this is a float, and distances will be rounded
      limit - the maximum size of the array to return; a negative number will make this have no limit
      Returns:
      a new Coord array containing some of the "on" cells in this Region
    • separatedRegionPoisson

      public Region separatedRegionPoisson(com.github.tommyettinger.random.EnhancedRandom rng, float minimumDistance)
      Removes all but a quasi-random group of "on" cells that each has at least minimumDistance between itself and any other cell in the returned Region. Modifies this Region in-place.
      Parameters:
      rng - an EnhancedRandom to randomly choose points; may be queried quite a lot for large Regions
      minimumDistance - the minimum distance between points to allow; this is a float, and distances will be rounded
      Returns:
      this, after modifications, for chaining
    • separatedRegionPoisson

      public Region separatedRegionPoisson(com.github.tommyettinger.random.EnhancedRandom rng, float minimumDistance, int limit)
      Removes all but a quasi-random group of "on" cells that each has at least minimumDistance between itself and any other cell in the returned Region. Modifies this Region in-place. This overload takes a limit; if limit is non-negative, it will be used as the maximum number of "on" cells to permit in the result. When there would otherwise be more "on" cells than the limit, this randomly chooses which ones to keep.
      Parameters:
      rng - an EnhancedRandom to randomly choose points; may be queried quite a lot for large Regions
      minimumDistance - the minimum distance between points to allow; this is a float, and distances will be rounded
      limit - the maximum size of the Region to return; a negative number will make this have no limit
      Returns:
      this, after modifications, for chaining
    • randomPortion

      public Coord[] randomPortion(com.github.tommyettinger.random.EnhancedRandom rng, int size)
    • randomRegion

      public Region randomRegion(com.github.tommyettinger.random.EnhancedRandom rng, int size)
    • contains

      public boolean contains(int x, int y)
    • isEmpty

      public boolean isEmpty()
      Specified by:
      isEmpty in interface Collection<Coord>
      Returns:
      Whether this zone is empty.
    • sum

      public static int[][] sum(Region... regions)
      Generates a 2D int array from an array or vararg of Regions, starting at all 0 and adding 1 to the int at a position once for every Region that has that cell as "on." This means if you give 8 Regions to this method, it can produce any number between 0 and 8 in a cell; if you give 16 Regions, then it can produce any number between 0 and 16 in a cell.
      Parameters:
      regions - an array or vararg of Regions; must all have the same width and height
      Returns:
      a 2D int array with the same width and height as the regions, where an int cell equals the number of given Regions that had an "on" cell at that position
    • sum

      public static int[][] sum(List<Region> regions)
      Generates a 2D int array from a List of Regions, starting at all 0 and adding 1 to the int at a position once for every Region that has that cell as "on." This means if you give 8 Regions to this method, it can produce any number between 0 and 8 in a cell; if you give 16 Regions, then it can produce any number between 0 and 16 in a cell.
      Parameters:
      regions - a List of Regions; must all have the same width and height
      Returns:
      a 2D int array with the same width and height as the regions, where an int cell equals the number of given Regions that had an "on" cell at that position
    • sumFloat

      public static float[][] sumFloat(Region... regions)
      Generates a 2D float array from an array or vararg of Regions, starting at all 0 and adding 1 to the float at a position once for every Region that has that cell as "on." This means if you give 8 Regions to this method, it can produce any number between 0 and 8 in a cell; if you give 16 Regions, then it can produce any number between 0 and 16 in a cell.
      Parameters:
      regions - an array or vararg of Regions; must all have the same width and height
      Returns:
      a 2D float array with the same width and height as the regions, where an float cell equals the number of given Regions that had an "on" cell at that position
    • sumFloat

      public static float[][] sumFloat(List<Region> regions)
      Generates a 2D float array from a List of Regions, starting at all 0 and adding 1 to the float at a position once for every Region that has that cell as "on." This means if you give 8 Regions to this method, it can produce any number between 0 and 8 in a cell; if you give 16 Regions, then it can produce any number between 0 and 16 in a cell.
      Parameters:
      regions - a List of Regions; must all have the same width and height
      Returns:
      a 2D float array with the same width and height as the regions, where an float cell equals the number of given Regions that had an "on" cell at that position
    • sumWeighted

      public static int[][] sumWeighted(Region[] regions, int[] weights)
      Generates a 2D int array from an array of Regions and an array of weights, starting the 2D result at all 0 and, for every Region that has that cell as "on," adding the int in the corresponding weights array at the position of that cell. This means if you give an array of 4 Regions to this method along with the weights 1, 2, 3, 4, it can produce a number between 0 and 10 in a cell (where 10 is used when all 4 Regions have a cell "on," since 1 + 2 + 3 + 4 == 10); if the weights are instead 1, 10, 100, 1000, then the results can vary between 0 and 1111, where 1111 is only if all Regions have a cell as "on." The weights array must have a length at least equal to the length of the regions array.
      Parameters:
      regions - an array of Regions; must all have the same width and height
      weights - an array of ints; must have length at least equal to regions' length
      Returns:
      a 2D int array with the same width and height as the regions, where an int cell equals the sum of the weights corresponding to Regions that had an "on" cell at that position
    • sumWeightedFloat

      public static float[][] sumWeightedFloat(Region[] regions, float[] weights)
      Generates a 2D float array from an array of Regions and an array of weights, starting the 2D result at all 0 and, for every Region that has that cell as "on," adding the float in the corresponding weights array at the position of that cell. This means if you give an array of 4 Regions to this method along with the weights 1, 2, 3, 4, it can produce a number between 0 and 10 in a cell (where 10 is used when all 4 Regions have a cell "on," since 1 + 2 + 3 + 4 == 10); if the weights are instead 1, 10, 100, 1000, then the results can vary between 0 and 1111, where 1111 is only if all Regions have a cell as "on." The weights array must have a length at least equal to the length of the regions array.
      Parameters:
      regions - an array of Regions; must all have the same width and height
      weights - an array of floats; must have length at least equal to regions' length
      Returns:
      a 2D float array with the same width and height as the regions, where an float cell equals the sum of the weights corresponding to Regions that had an "on" cell at that position
    • sumInto

      public static int[][] sumInto(int[][] existing, Region... regions)
      Adds to an existing 2D int array with an array or vararg of Regions, adding 1 to the int in existing at a position once for every Region that has that cell as "on." This means if you give 8 Regions to this method, it can increment by any number between 0 and 8 in a cell; if you give 16 Regions, then it can increase the value in existing by any number between 0 and 16 in a cell.
      Parameters:
      existing - a non-null 2D int array that will have each cell incremented by the sum of the Regions
      regions - an array or vararg of Regions; must all have the same width and height
      Returns:
      existing, after modification, where an int cell will be changed by the number of given Regions that had an "on" cell at that position
    • sumIntoFloat

      public static float[][] sumIntoFloat(float[][] existing, Region... regions)
      Adds to an existing 2D float array with an array or vararg of Regions, adding 1 to the float in existing at a position once for every Region that has that cell as "on." This means if you give 8 Regions to this method, it can increment by any number between 0 and 8 in a cell; if you give 16 Regions, then it can increase the value in existing by any number between 0 and 16 in a cell.
      Parameters:
      existing - a non-null 2D float array that will have each cell incremented by the sum of the Regions
      regions - an array or vararg of Regions; must all have the same width and height
      Returns:
      existing, after modification, where a float cell will be changed by the number of given Regions that had an "on" cell at that position
    • bitSum

      public static int[][] bitSum(Region... regions)
      Generates a 2D int array from an array or vararg of Regions, treating each cell in the nth region as the nth bit of the int at the corresponding x,y cell in the int array. This means if you give 8 Regions to this method, it can produce any 8-bit number in a cell (0-255); if you give 16 Regions, then it can produce any 16-bit number (0-65535).
      Parameters:
      regions - an array or vararg of Regions; must all have the same width and height
      Returns:
      a 2D int array with the same width and height as the regions, with bits per int taken from the regions
    • dijkstraScan

      public int[][] dijkstraScan(int[][] into, Coord goal)
      A crude approximation of DijkstraMap's scan() method for when DijkstraMap isn't available. Starting at goal, this floods outward (4-way) as with flood(Region), modifying into so each cell reached during the course of repeated flooding has an int value equal to the (Manhattan) distance from goal to that cell, and all other cells will be set to Integer.MAX_VALUE. This will call flood(Region) until it can't reach any more cells. This returns into, after modifications.
      Parameters:
      into - a 2D int array that will have all reachable cells assigned their distance from goal, and all others to Integer.MAX_VALUE
      goal - the starting point for the scan/flood-fill; into will be assigned 0 at this point
      Returns:
      into, after modifications
    • dijkstraScan

      public int[][] dijkstraScan(int[][] into, Coord goal, int limit)
      A crude approximation of DijkstraMap's scan() method for when DijkstraMap isn't available. Starting at goal, this floods outward (4-way) as with flood(Region), modifying into so each cell reached during the course of repeated flooding has an int value equal to the (Manhattan) distance from goal to that cell, and all other cells will be set to Integer.MAX_VALUE. The limit is the exclusive upper bound for the greatest distance from the goal this will change; this will call flood(Region) at most limit times, and can call it fewer times if it tries to flood but can't reach any more cells. This returns into, after modifications.
      Parameters:
      into - a 2D int array that will have all reachable cells assigned their distance from goal, and all others to Integer.MAX_VALUE
      goal - the starting point for the scan/flood-fill; into will be assigned 0 at this point
      limit - the exclusive upper bound on the distance this can travel from the goal
      Returns:
      into, after modifications
    • dijkstraScan

      public int[][] dijkstraScan(int[][] into, Region goals)
      A crude approximation of DijkstraMap's scan() method for when DijkstraMap isn't available. Starting at each "on" cell in goals, this floods outward (4-way) as with flood(Region), modifying into so each cell reached during the course of repeated flooding has an int value equal to the (Manhattan) distance from goal to that cell, and all other cells will be set to Integer.MAX_VALUE. This will call flood(Region) until it can't reach any more cells. Note, this modifies both into and goals, but usually the result in goals isn't very useful (you may want to get its size() to know how many cells were affected, but it can't tell you the distance for any particular cell). This returns into, after modifications.
      Parameters:
      into - a 2D int array that will have all reachable cells assigned their distance from goal, and all others to Integer.MAX_VALUE
      goals - the starting points for the scan/flood-fill; will be modified by repeatedly calling flood()
      Returns:
      into, after modifications
    • dijkstraScan

      public int[][] dijkstraScan(int[][] into, Region goals, int limit)
      A crude approximation of DijkstraMap's scan() method for when DijkstraMap isn't available. Starting at each "on" cell in goals, this floods outward (4-way) as with flood(Region), modifying into so each cell reached during the course of repeated flooding has an int value equal to the (Manhattan) distance from goal to that cell, and all other cells will be set to Integer.MAX_VALUE. The limit is the exclusive upper bound for the greatest distance from a goal this will change; this will call flood(Region) at most limit times, and can call it fewer times if it tries to flood but can't reach any more cells. Note, this modifies both into and goals, but usually the result in goals isn't very useful (you may want to get its size() to know how many cells were affected, but it can't tell you the distance for any particular cell). This returns into, after modifications.
      Parameters:
      into - a 2D int array that will have all reachable cells assigned their distance from goal, and all others to Integer.MAX_VALUE
      goals - the starting points for the scan/flood-fill; will be modified by repeatedly calling flood()
      limit - the exclusive upper bound on the distance this can travel from the goal
      Returns:
      into, after modifications
    • equals

      public boolean equals(Object o)
      Specified by:
      equals in interface Collection<Coord>
      Overrides:
      equals in class Object
    • hashCode

      public int hashCode()
      Specified by:
      hashCode in interface Collection<Coord>
      Overrides:
      hashCode in class Object
    • hash64

      public long hash64()
    • hash64

      public long hash64(long seed)
      Computes a 64-bit hash code of this Region given a 64-bit seed; even if given two very similar seeds, this should produce very different hash codes for the same Region.
      Meant for potential use in Bloom filters. Uses Hasher's algorithm(s).
      Parameters:
      seed - a seed that will determine how the hashing algorithm works; all 64 bits are used.
      Returns:
      a 64-bit hash code for this Region
    • stringSerialize

      public String stringSerialize()
    • stringDeserialize

      public static Region stringDeserialize(String s)
    • of

      public static Region of(int width, int height, long... data)
      Constructs a Region using a vararg for data. Primarily meant for generated code, since stringSerialize() produces a String that happens to be a valid parameter list for this method.
      Parameters:
      width - width of the Region to produce
      height - height of the Region to produce
      data - array or vararg of long containing the exact data, probably from an existing Region
      Returns:
      a new Region with the given width, height, and data
    • toCompressedString

      public String toCompressedString()
      Compresses this Region into a UTF-16 String and returns the String without modifying this Region. Uses HilbertCurve's algorithm and data to compress this Region in 256x128 blocks, storing the HilbertCurve data as chars with values from 256 to 33023 (a concept also used in LZSEncoding), and using ASCII semicolons to separate them or store other info (just width and height, which are given first as 16 hex digits). This finishes by running the result through LZSEncoding, a combination which typically gets very good compression.
      Returns:
      a String that could be used to reconstruct this Region using decompress(String)
    • decompress

      public static Region decompress(String compressed)
      Decompresses a String returned by toCompressedString(), returning a new Region with identical width, height, and contents to the Region before compression. This decompresses the LZSEncoding applied to the data, then decompresses the HilbertCurve RLE data to get the original Region back.
      Parameters:
      compressed - a String that was compressed by toCompressedString(), without changes
      Returns:
      a new copy of the Region that was previously compressed
    • decompressInto

      public Region decompressInto(String compressed)
      Decompresses a String returned by toCompressedString(), and assigns into this region the width, height, and contents of the data before compression. This decompresses the LZSEncoding applied to the data, then decompresses the HilbertCurve RLE data to get the original Region's size and contents back.
      Parameters:
      compressed - a String that was compressed by toCompressedString(), without changes
      Returns:
      this, for chaining
    • contains

      public boolean contains(Object o)
      Specified by:
      contains in interface Collection<Coord>
    • iterator

      public Iterator<Coord> iterator()
      Specified by:
      iterator in interface Collection<Coord>
      Specified by:
      iterator in interface Iterable<Coord>
    • toArray

      public Object[] toArray()
      Specified by:
      toArray in interface Collection<Coord>
    • toArray

      public <T> T[] toArray(T[] a)
      Specified by:
      toArray in interface Collection<Coord>
    • add

      public boolean add(Coord coord)
      Specified by:
      add in interface Collection<Coord>
    • clear

      public void clear()
      Specified by:
      clear in interface Collection<Coord>
    • remove

      public boolean remove(Object o)
      Specified by:
      remove in interface Collection<Coord>
    • containsAll

      public boolean containsAll(Collection<?> c)
      Specified by:
      containsAll in interface Collection<Coord>
    • addAll

      public boolean addAll(Collection<? extends Coord> c)
      Specified by:
      addAll in interface Collection<Coord>
    • removeAll

      public boolean removeAll(Collection<?> c)
      Specified by:
      removeAll in interface Collection<Coord>
    • retainAll

      public boolean retainAll(Collection<?> c)
      Specified by:
      retainAll in interface Collection<Coord>
    • deteriorate

      public Region deteriorate(com.github.tommyettinger.random.EnhancedRandom rng, int preservation)
      Randomly removes points from a Region, with larger values for preservation keeping more of the existing shape intact. If preservation is 1, roughly 1/2 of all points will be removed; if 2, roughly 1/4, if 3, roughly 1/8, and so on, so that preservation can be thought of as a negative exponent of 2.
      Parameters:
      rng - used to determine random factors
      preservation - roughly what degree of points to remove (higher keeps more); removes about 1/(2^preservation) points
      Returns:
      a randomly modified change to this Region
    • deteriorate

      public Region deteriorate(com.github.tommyettinger.random.EnhancedRandom random, float preservation)
      Randomly removes points from a Region, with preservation as a fraction between 1.0 (keep all) and 0.0 (remove all). If preservation is 0.5, roughly 1/2 of all points will be removed; if 0.25, roughly 3/4 will be removed (roughly 0.25 will be _kept_), if 0.8, roughly 1/5 will be removed (and about 0.8 will be kept), and so on. Preservation must be between 0.0 and 1.0 for this to have the intended behavior; 1.0 or higher will keep all points without change (returning this Region), while anything less than 0.015625 (1.0/64) will empty this Region (using empty()) and then return it. The parameter random can be a plain EnhancedRandom, but will be much faster and have less potential for patterns or artifacts in the output if you use WhiskerRandom or another higher-quality subclass.
      Parameters:
      random - a EnhancedRandom or a recommended subclass, like WhiskerRandom
      preservation - the rough fraction of points to keep, between 0.0 and 1.0
      Returns:
      a randomly modified change to this Region
    • toggle

      public Region toggle(int x, int y)
      Changes the on/off state of the cell with the given x and y, making an on cell into an off cell, or an off cell into an on cell.
      This was called flip(), but that name would be confusing since flipping a rectangular area usually means reversing an axis.
      Parameters:
      x - the x position of the cell to flip
      y - the y position of the cell to flip
      Returns:
      this for chaining, modified
    • mirrorY

      public Region mirrorY()
      Returns a new Region that has been mirrored along the rightmost edge, parallel to the y-axis. The new Region will have exactly twice the width, the additional width will have the contents of the original GreasesRegion in reversed order. The positions shared by both Regions will be the same, that is, any area not added to the original will be equal to the original.
      Returns:
      a new Region with twice the width of this, that is mirrored along the rightmost edge
    • contains

      public boolean contains(Coord c)
      Checks if c is present in this Region. Returns true if and only if c is present in this Region as an "on" cell. This will never be true if c is null, has negative x or y, has a value for x that is equal to or greater than width, or has a value for y that is equal to or greater than height, but none of those conditions will cause Exceptions to be thrown.
      Parameters:
      c - a Coord to try to find in this Region; if null this will always return false
      Returns:
      true if c is an "on" cell in this Region, or false otherwise, including if c is null
    • xBound

      public int xBound(boolean findSmallest)
      Parameters:
      findSmallest - if true, finds the smallest x-coordinate value; if false, finds the biggest.
      Returns:
      The x-coordinate of the Coord within this that has the smallest (or biggest) x-coordinate. Or -1 if the zone is empty.
    • yBound

      public int yBound(boolean findSmallest)
      Parameters:
      findSmallest - if true, finds the smallest y-coordinate value; if false, finds the biggest.
      Returns:
      The y-coordinate of the Coord within this that has the smallest (or biggest) y-coordinate. Or -1 if the zone is empty.