All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.pepsoft.util.BitField Maven / Gradle / Ivy

The newest version!
package org.pepsoft.util;

import java.awt.*;
import java.util.BitSet;
import java.util.HashMap;
import java.util.Map;

/**
 * An unlimited (except by the range of the {@code int} type)
 * two-dimensional field of bits, initially {@code false}.
 *
 * 

This class is not thread-safe. */ public class BitField { /** * Set a bit. * * @param x The X coordinate of the bit to set. * @param y The Y coordinate of the bit to set. */ public void set(int x, int y) { if ((x != cachedX) || (y != cachedY)) { cachedBits = booleans.computeIfAbsent(new Point(x >> 7, y >> 7), c -> new BitSet(16384)); cachedX = x; cachedY = y; } if (cachedBits == null) { // This might happen if reset() or get() was previously invoked for // these coordinates and there was no bitset created for them yet cachedBits = new BitSet(16384); booleans.put(new Point(x >> 7, y >> 7), cachedBits); } cachedBits.set(((x & 0x7f) << 7) | (y & 0x7f)); } /** * Reset a bit. * * @param x The X coordinate of the bit to reset. * @param y The Y coordinate of the bit to reset. */ public void reset(int x, int y) { if ((x != cachedX) || (y != cachedY)) { cachedBits = booleans.get(new Point(x >> 7, y >> 7)); cachedX = x; cachedY = y; } if (cachedBits != null) { cachedBits.clear(((x & 0x7f) << 7) | (y & 0x7f)); } } /** * Get a bit. * * @param x The X coordinate of the bit to get. * @param y The Y coordinate of the bit to get. * @return {@code true} if the bit is set, {@code false} * otherwise. */ public boolean get(int x, int y) { if ((x != cachedX) || (y != cachedY)) { cachedBits = booleans.get(new Point(x >> 7, y >> 7)); cachedX = x; cachedY = y; } if (cachedBits != null) { return cachedBits.get(((x & 0x7f) << 7) | (y & 0x7f)); } else { return false; } } /** * Get the bounding box of all the bits that are set. * * @return The bounding box of all the bits that are set, or * {@code null} if no bits are set. */ public Rectangle getBoundingBox() { // TODO throw new UnsupportedOperationException(); } /** * Perform a task for all bits that are set. * * @param visitor The task to perform. * @return {@code true} if the visitor returned {@code true} for * every bit and every bit was therefore visited. {@code false} if the * visitor returned {@code false} for some bit and not all bits may * have been visited. */ public boolean visitSetBits(BitVisitor visitor) { for (Map.Entry entry: booleans.entrySet()) { int xOffset = entry.getKey().x << 7; int yOffset = entry.getKey().y << 7; BitSet bits = entry.getValue(); for (int i = bits.nextSetBit(0); i >= 0; i = bits.nextSetBit(i+1)) { int x = (i & 0x3f80) >> 7; int y = i & 0x7f; if (! visitor.visitBit(xOffset | x, yOffset | y, true)) { return false; } } } return true; } private int cachedX, cachedY; private BitSet cachedBits; private final Map booleans = new HashMap<>(); /** * A visitor of bits on a 2D plane. */ @FunctionalInterface public interface BitVisitor { /** * Visit a specific bit. * * @param x The X coordinate of the bit on the 2D plane. * @param y The Y coordinate of the bit on the 2D plane. * @param bit Whether the bit is set. * @return Should return {@code true} to indicate that processing * should continue, or {@code false} to indicate that processing * may be aborted. */ boolean visitBit(int x, int y, boolean bit); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy