//[h]sphere can now generate ellipsoid (stretched sphere) shapes

This commit is contained in:
TomyLobo 2011-09-02 21:38:38 +02:00
parent 780d07a9ba
commit 8c0d0f9ed4
4 changed files with 99 additions and 42 deletions

View File

@ -1920,37 +1920,60 @@ public class EditSession {
} }
/** /**
* Makes a sphere. * Makes a sphere or ellipsoid.
* *
* @param pos * @param pos Center of the sphere or ellipsoid
* @param block * @param block The block pattern to use
* @param radius * @param radiusX The sphere/ellipsoid's largest north/south extent
* @param filled * @param radiusY The sphere/ellipsoid's largest up/down extent
* @param radiusZ The sphere/ellipsoid's largest east/west extent
* @param filled If false, only a shell will be generated.
* @return number of blocks changed * @return number of blocks changed
* @throws MaxChangedBlocksException * @throws MaxChangedBlocksException
*/ */
public int makeSphere(Vector pos, Pattern block, double radius, public int makeSphere(Vector pos, Pattern block, double radiusX, double radiusY, double radiusZ, boolean filled) throws MaxChangedBlocksException {
boolean filled) throws MaxChangedBlocksException {
int affected = 0; int affected = 0;
radius += 0.5; radiusX += 0.5;
final double radiusSq = radius*radius; radiusY += 0.5;
final double radius1Sq = (radius - 1)*(radius - 1); radiusZ += 0.5;
final int ceilRadius = (int) Math.ceil(radius); final double invRadiusX = 1 / radiusX;
for (int x = 0; x <= ceilRadius; ++x) { final double invRadiusY = 1 / radiusY;
for (int y = 0; y <= ceilRadius; ++y) { final double invRadiusZ = 1 / radiusZ;
for (int z = 0; z <= ceilRadius; ++z) {
double dSq = lengthSq(x, y, z);
if (dSq > radiusSq) final int ceilRadiusX = (int) Math.ceil(radiusX);
continue; final int ceilRadiusY = (int) Math.ceil(radiusY);
final int ceilRadiusZ = (int) Math.ceil(radiusZ);
double nextXn = 0;
forX:
for (int x = 0; x <= ceilRadiusX; ++x) {
final double xn = nextXn;
nextXn = (x+1)*invRadiusX;
double nextYn = 0;
forY:
for (int y = 0; y <= ceilRadiusY; ++y) {
final double yn = nextYn;
nextYn = (y+1)*invRadiusY;
double nextZn = 0;
forZ:
for (int z = 0; z <= ceilRadiusZ; ++z) {
final double zn = nextZn;
nextZn = (z+1)*invRadiusZ;
double distanceSq = lengthSq(xn, yn, zn);
if (distanceSq > 1) {
if (z == 0) {
if (y == 0)
break forX;
break forY;
}
break forZ;
}
if (!filled) { if (!filled) {
if (dSq < radius1Sq) if (lengthSq(nextXn, yn, zn) <= 1 && lengthSq(xn, nextYn, zn) <= 1 && lengthSq(xn, yn, nextZn) <= 1)
continue;
if (lengthSq(x+1, y, z) <= radiusSq && lengthSq(x, y+1, z) <= radiusSq && lengthSq(x, y, z+1) <= radiusSq)
continue; continue;
} }
@ -1985,7 +2008,7 @@ public class EditSession {
return affected; return affected;
} }
private static final double lengthSq(int x, int y, int z) { private static final double lengthSq(double x, double y, double z) {
return x*x + y*y + z*z; return x*x + y*y + z*z;
} }

View File

@ -80,8 +80,8 @@ public class GenerationCommands {
@Command( @Command(
aliases = {"/hsphere"}, aliases = {"/hsphere"},
usage = "<block> <radius> [raised?] ", usage = "<block> <radius>[,<radius>,<radius>] [raised?] ",
desc = "Generate a hollow sphere", desc = "Generate a hollow sphere. If you specify 3 radiuses separated by commas, an ellipsoid with the dimensions x,y,z will be generated.",
min = 2, min = 2,
max = 3 max = 3
) )
@ -91,19 +91,36 @@ public class GenerationCommands {
LocalSession session, LocalPlayer player, EditSession editSession) LocalSession session, LocalPlayer player, EditSession editSession)
throws WorldEditException { throws WorldEditException {
Pattern block = we.getBlockPattern(player, args.getString(0)); final Pattern block = we.getBlockPattern(player, args.getString(0));
double radius = Math.max(1, args.getDouble(1)); String[] radiuses = args.getString(1).split(",");
boolean raised = args.argsLength() > 2 final double radiusX, radiusY, radiusZ;
? (args.getString(2).equalsIgnoreCase("true") switch (radiuses.length) {
|| args.getString(2).equalsIgnoreCase("yes")) case 1:
: false; radiusX = radiusY = radiusZ = Math.max(1, Double.parseDouble(radiuses[0]));
break;
case 3:
radiusX = Math.max(1, Double.parseDouble(radiuses[0]));
radiusY = Math.max(1, Double.parseDouble(radiuses[1]));
radiusZ = Math.max(1, Double.parseDouble(radiuses[2]));
break;
default:
player.printError("You must either specify 1 or 3 radius values.");
return;
}
final boolean raised;
if (args.argsLength() > 2)
raised = args.getString(2).equalsIgnoreCase("true") || args.getString(2).equalsIgnoreCase("yes");
else
raised = false;
Vector pos = session.getPlacementPosition(player); Vector pos = session.getPlacementPosition(player);
if (raised) { if (raised) {
pos = pos.add(0, radius, 0); pos = pos.add(0, radiusY, 0);
} }
int affected = editSession.makeSphere(pos, block, radius, false); int affected = editSession.makeSphere(pos, block, radiusX, radiusY, radiusZ, false);
player.findFreePosition(); player.findFreePosition();
player.print(affected + " block(s) have been created."); player.print(affected + " block(s) have been created.");
} }
@ -111,7 +128,7 @@ public class GenerationCommands {
@Command( @Command(
aliases = {"/sphere"}, aliases = {"/sphere"},
usage = "<block> <radius> [raised?] ", usage = "<block> <radius> [raised?] ",
desc = "Generate a filled sphere", desc = "Generate a filled sphere. If you specify 3 radiuses separated by commas, an ellipsoid with the dimensions x,y,z will be generated.",
min = 2, min = 2,
max = 3 max = 3
) )
@ -122,18 +139,35 @@ public class GenerationCommands {
throws WorldEditException { throws WorldEditException {
Pattern block = we.getBlockPattern(player, args.getString(0)); Pattern block = we.getBlockPattern(player, args.getString(0));
double radius = Math.max(1, args.getDouble(1)); String[] radiuses = args.getString(1).split(",");
boolean raised = args.argsLength() > 2 final double radiusX, radiusY, radiusZ;
? (args.getString(2).equalsIgnoreCase("true") switch (radiuses.length) {
|| args.getString(2).equalsIgnoreCase("yes")) case 1:
: false; radiusX = radiusY = radiusZ = Math.max(1, Double.parseDouble(radiuses[0]));
break;
case 3:
radiusX = Math.max(1, Double.parseDouble(radiuses[0]));
radiusY = Math.max(1, Double.parseDouble(radiuses[1]));
radiusZ = Math.max(1, Double.parseDouble(radiuses[2]));
break;
default:
player.printError("You must either specify 1 or 3 radius values.");
return;
}
final boolean raised;
if (args.argsLength() > 2)
raised = args.getString(2).equalsIgnoreCase("true") || args.getString(2).equalsIgnoreCase("yes");
else
raised = false;
Vector pos = session.getPlacementPosition(player); Vector pos = session.getPlacementPosition(player);
if (raised) { if (raised) {
pos = pos.add(0, radius, 0); pos = pos.add(0, radiusY, 0);
} }
int affected = editSession.makeSphere(pos, block, radius, true); int affected = editSession.makeSphere(pos, block, radiusX, radiusY, radiusZ, true);
player.findFreePosition(); player.findFreePosition();
player.print(affected + " block(s) have been created."); player.print(affected + " block(s) have been created.");
} }

View File

@ -30,6 +30,6 @@ public class HollowSphereBrush implements Brush {
public void build(EditSession editSession, Vector pos, Pattern mat, double size) public void build(EditSession editSession, Vector pos, Pattern mat, double size)
throws MaxChangedBlocksException { throws MaxChangedBlocksException {
editSession.makeSphere(pos, mat, size, false); editSession.makeSphere(pos, mat, size, size, size, false);
} }
} }

View File

@ -30,6 +30,6 @@ public class SphereBrush implements Brush {
public void build(EditSession editSession, Vector pos, Pattern mat, double size) public void build(EditSession editSession, Vector pos, Pattern mat, double size)
throws MaxChangedBlocksException { throws MaxChangedBlocksException {
editSession.makeSphere(pos, mat, size, true); editSession.makeSphere(pos, mat, size, size, size, true);
} }
} }