/**
* Copyright (c) 2011-2015, SpaceToad and the BuildCraft Team
* http://www.mod-buildcraft.com
* <p/>
* BuildCraft is distributed under the terms of the Minecraft Mod Public
* License 1.0, or MMPL. Please check the contents of the license located in
* http://www.mod-buildcraft.com/MMPL-1.0.txt
*/
package buildcraft.core.builders.patterns;
import net.minecraft.world.World;
import buildcraft.api.statements.IStatementParameter;
import buildcraft.core.Box;
import buildcraft.core.blueprints.Template;
public class PatternCylinder extends FillerPattern {
public PatternCylinder() {
super("cylinder");
}
@Override
public int maxParameters() {
return 1;
}
@Override
public int minParameters() {
return 1;
}
@Override
public IStatementParameter createParameter(int index) {
return new PatternParameterHollow(true);
}
@Override
public Template getTemplate(Box box, World world, IStatementParameter[] parameters) {
Template result = new Template(box.sizeX(), box.sizeY(), box.sizeZ());
boolean filled = parameters.length > 0 && ((PatternParameterHollow) parameters[0]).filled;
int xMin = 0;
int yMin = 0;
int zMin = 0;
int xMax = box.sizeX() - 1;
int yMax = box.sizeY() - 1;
int zMax = box.sizeZ() - 1;
int xFix = (xMax - xMin) % 2;
int zFix = (zMax - zMin) % 2;
int xCenter = (xMax + xMin) / 2
+ (xMax + xMin < 0 && xFix == 1 ? -1 : 0);
int zCenter = (zMax + zMin) / 2
+ (zMax + zMin < 0 && zFix == 1 ? -1 : 0);
int xRadius = (xMax - xMin) / 2;
int zRadius = (zMax - zMin) / 2;
if (xRadius == 0 || zRadius == 0) {
fill(xMin, yMin, zMin, xMax, yMax, zMax, result);
return result;
}
int dx = xRadius, dz = 0;
int xChange = zRadius * zRadius * (1 - 2 * xRadius);
int zChange = xRadius * xRadius;
int ellipseError = 0;
int twoASquare = 2 * xRadius * xRadius;
int twoBSquare = 2 * zRadius * zRadius;
int stoppingX = twoBSquare * xRadius;
int stoppingZ = 0;
if (twoASquare > 0) {
while (stoppingX >= stoppingZ) {
if (filled) {
fillSquare(xCenter, zCenter, dx, dz, xFix, zFix, yMin,
yMax, result);
} else {
fillFourColumns(xCenter, zCenter, dx, dz, xFix, zFix, yMin,
yMax, result);
}
++dz;
stoppingZ += twoASquare;
ellipseError += zChange;
zChange += twoASquare;
if (2 * ellipseError + xChange > 0) {
--dx;
stoppingX -= twoBSquare;
ellipseError += xChange;
xChange += twoBSquare;
}
}
}
dx = 0;
dz = zRadius;
xChange = zRadius * zRadius;
zChange = xRadius * xRadius * (1 - 2 * zRadius);
ellipseError = 0;
stoppingX = 0;
stoppingZ = twoASquare * zRadius;
if (twoBSquare > 0) {
while (stoppingX <= stoppingZ) {
if (filled) {
fillSquare(xCenter, zCenter, dx, dz, xFix, zFix, yMin,
yMax, result);
} else {
fillFourColumns(xCenter, zCenter, dx, dz, xFix, zFix, yMin,
yMax, result);
}
++dx;
stoppingX += twoBSquare;
ellipseError += xChange;
xChange += twoBSquare;
if (2 * ellipseError + zChange > 0) {
--dz;
stoppingZ -= twoASquare;
ellipseError += zChange;
zChange += twoASquare;
}
}
}
return result;
}
private boolean fillSquare(int xCenter, int zCenter, int dx, int dz,
int xFix, int zFix, int yMin, int yMax, Template template) {
int x1, x2, z1, z2;
x1 = xCenter + dx + xFix;
z1 = zCenter + dz + zFix;
x2 = xCenter - dx;
z2 = zCenter + dz + zFix;
fill(x2, yMin, z2, x1, yMax, z1, template);
x1 = xCenter - dx;
z1 = zCenter - dz;
fill(x1, yMin, z1, x2, yMax, z2, template);
x2 = xCenter + dx + xFix;
z2 = zCenter - dz;
fill(x1, yMin, z1, x2, yMax, z2, template);
x1 = xCenter + dx + xFix;
z1 = zCenter + dz + zFix;
fill(x2, yMin, z2, x1, yMax, z1, template);
return true;
}
private boolean fillFourColumns(int xCenter, int zCenter, int dx, int dz,
int xFix, int zFix, int yMin, int yMax, Template template) {
int x, z;
x = xCenter + dx + xFix;
z = zCenter + dz + zFix;
fill(x, yMin, z, x, yMax, z, template);
x = xCenter - dx;
z = zCenter + dz + zFix;
fill(x, yMin, z, x, yMax, z, template);
x = xCenter - dx;
z = zCenter - dz;
fill(x, yMin, z, x, yMax, z, template);
x = xCenter + dx + xFix;
z = zCenter - dz;
fill(x, yMin, z, x, yMax, z, template);
return true;
}
}