package org.openpixi.pixi.physics.movement.boundary;
import org.openpixi.pixi.physics.util.DoubleBox;
import org.openpixi.pixi.physics.util.Point;
/**
* Identifies different boundary regions of the simulation area.
* The boundary regions lie outside of the simulation area.
*/
public class BoundaryRegions {
/*
* Specific boundary is specified by the combination of X and Y values.
* E.g. top-left is X_MIN + Y_MIN.
*/
public static final int X_MIN = 0;
public static final int X_CENTER = 1;
public static final int X_MAX = 2;
public static final int Y_MIN = 0;
public static final int Y_CENTER = 3;
public static final int Y_MAX = 6;
public static final int NUM_OF_REGIONS = X_MAX + Y_MAX + 1;
/** Regions which share an edge with the simulation area. */
public static int[] EDGE_REGIONS = {
X_MIN + Y_CENTER,
X_MAX + Y_CENTER,
Y_MIN + X_CENTER,
Y_MAX + X_CENTER
};
/** Regions which share a corner with the simulation area. */
public static int[] CORNER_REGIONS = {
X_MIN + Y_MIN,
X_MAX + Y_MIN,
X_MIN + Y_MAX,
X_MAX + Y_MAX
};
/** Box around the simulation area. */
private DoubleBox simulationArea;
public BoundaryRegions(DoubleBox simulationArea) {
this.simulationArea = simulationArea;
}
public int getRegion(DoubleBox particleBox) {
return getRegion(
particleBox.xmin(), particleBox.xmax(),
particleBox.ymin(), particleBox.ymax());
}
public int getRegion(double x, double y) {
return getRegion(x,x,y,y);
}
/**
* Gets the region based on simulation area intersection with box.
* This way we can check particle's circumference to be in a boundary region.
*/
private int getRegion(double xmin, double xmax, double ymin, double ymax) {
int xidx;
int yidx;
if (xmin < simulationArea.xmin()) {
xidx = X_MIN;
} else if (xmax >= simulationArea.xmax()) {
xidx = X_MAX;
} else {
xidx = X_CENTER;
}
if (ymin < simulationArea.ymin()) {
yidx = Y_MIN;
} else if (ymax >= simulationArea.ymax()) {
yidx = Y_MAX;
} else {
yidx = Y_CENTER;
}
return xidx + yidx;
}
/**
* Decomposes the region id to X and Y components.
*/
public static Point decomposeRegionID(int regionID) {
int y = findHighestPossibleY(regionID);
int x = findX(y, regionID);
return new Point(x, y);
}
/**
* Returns sign of the region.
* E.g.:
* X_MIN + Y_MIN = (-1, -1)
* X_CENTER + Y_MAX = (0, 1)
*/
public static Point getSign(int regionID) {
Point region = decomposeRegionID(regionID);
return new Point(region.x - 1, region.y / 3 - 1);
}
private static int findX(int y, int regionID) {
int potentialX = regionID - y;
assert X_MIN <= potentialX && potentialX <= X_MAX;
return potentialX;
}
private static int findHighestPossibleY(int regionID) {
int highetsY = -1;
for (int y = Y_MIN; y <= Y_MAX; ++y) {
if (y <= regionID) {
highetsY = y;
}
}
assert highetsY != -1;
return highetsY;
}
}