package com.forgeessentials.commons.selections;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class AreaBase {
protected Point high;
protected Point low;
/**
* Points are inclusive.
*
* @param p1
* @param p2
*/
public AreaBase(Point p1, Point p2)
{
low = getMinPoint(p1, p2);
high = getMaxPoint(p1, p2);
}
public int getXLength()
{
return high.getX() - low.getX() + 1;
}
public int getYLength()
{
return high.getY() - low.getY() + 1;
}
public int getZLength()
{
return high.getZ() - low.getZ() + 1;
}
public Point getHighPoint()
{
return high;
}
public Point getLowPoint()
{
return low;
}
public Point getSize()
{
return new Point(high.x - low.x, high.y - low.y, high.z - low.z);
}
/**
* Get the lowest XYZ coordinate in OOBB [p1,p2]
*/
public static Point getMinPoint(Point p1, Point p2)
{
return new Point(Math.min(p1.getX(), p2.getX()), Math.min(p1.getY(), p2.getY()), Math.min(p1.getZ(), p2.getZ()));
}
/**
* Get the highest XYZ coordinate in OOBB [p1,p2]
*/
public static Point getMaxPoint(Point p1, Point p2)
{
return new Point(Math.max(p1.getX(), p2.getX()), Math.max(p1.getY(), p2.getY()), Math.max(p1.getZ(), p2.getZ()));
}
/**
* Determines if a given point is within the bounds of an area.
*
* @param p
* Point to check against the Area
* @return True, if the Point p is inside the area.
*/
public boolean contains(Point p)
{
return high.isGreaterEqualThan(p) && low.isLessEqualThan(p);
}
/**
* checks if this area contains with another
*
* @param area
* to check against this area
* @return True, AreaBAse area is completely within this area
*/
public boolean contains(AreaBase area)
{
return this.contains(area.high) && this.contains(area.low);
}
/**
* checks if this area is overlapping with another
*
* @param area
* to check against this area
* @return True, if the given area overlaps with this one.
*/
public boolean intersectsWith(AreaBase area)
{
return this.getIntersection(area) != null;
}
/**
* @param area
* The area to be checked.
* @return NULL if the areas to do not intersect. Argument if this area completely contains the argument.
*/
public AreaBase getIntersection(AreaBase area)
{
if (area == null)
{
return null;
}
boolean hasIntersection = false;
Point p = new Point(0, 0, 0);
Point minp = new Point(0, 0, 0);
Point maxp = new Point(0, 0, 0);
int[] xs = { this.low.x, this.high.x, area.low.x, area.high.x };
int[] ys = { this.low.y, this.high.y, area.low.y, area.high.y };
int[] zs = { this.low.z, this.high.z, area.low.z, area.high.z };
for (int x : xs)
{
p.setX(x);
for (int y : ys)
{
p.setY(y);
for (int z : zs)
{
p.setZ(z);
if (this.contains(p) && area.contains(p))
{
if (!hasIntersection)
{
hasIntersection = true;
minp = p;
maxp = p;
}
else
{
minp = AreaBase.getMinPoint(minp, p);
maxp = AreaBase.getMaxPoint(maxp, p);
}
}
}
}
}
if (!hasIntersection)
{
return null;
}
else
{
return new AreaBase(minp, maxp);
}
}
public boolean makesCuboidWith(AreaBase area)
{
boolean alignX = low.getX() == area.low.getX() && high.getX() == area.high.getX();
boolean alignY = low.getY() == area.low.getY() && high.getY() == area.high.getY();
boolean alignZ = low.getZ() == area.low.getZ() && high.getZ() == area.high.getZ();
return alignX || alignY || alignZ;
}
/**
* @param area
* The area to be checked.
* @return NULL if the areas to do not make a cuboid together.
*/
public AreaBase getUnity(AreaBase area)
{
if (!makesCuboidWith(area))
{
return null;
}
else
{
return new AreaBase(getMinPoint(low, area.low), getMaxPoint(high, area.high));
}
}
public void redefine(Point p1, Point p2)
{
low = getMinPoint(p1, p2);
high = getMaxPoint(p1, p2);
}
public AreaBase copy()
{
return new AreaBase(low, high);
}
@Override
public String toString()
{
return "{" + high.toString() + " , " + low.toString() + " }";
}
private static final Pattern pattern = Pattern.compile("\\s*\\{\\s*(\\[.*\\])\\s*,\\s*(\\[.*\\])\\s*\\}\\s*");
public static AreaBase fromString(String value)
{
Matcher match = pattern.matcher(value);
if (!match.matches())
return null;
Point p1 = Point.fromString(match.group(1));
Point p2 = Point.fromString(match.group(2));
if (p1 == null || p2 == null)
return null;
return new AreaBase(p1, p2);
}
public Point getCenter()
{
return new Point((high.x + low.x) / 2, (high.y + low.y) / 2, (high.z + low.z) / 2);
}
}