Merge pull request #536 from enveeed/feature/line-convex-selection

Add //line support for convex polyhedral selections
This commit is contained in:
Octavia Togami 2019-12-06 23:21:17 -08:00 committed by GitHub
commit d132f08bc4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 69 additions and 43 deletions

View File

@ -19,6 +19,7 @@
package com.sk89q.worldedit;
import com.google.common.collect.ImmutableList;
import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.event.extent.EditSessionEvent;
@ -2186,12 +2187,33 @@ public int hollowOutRegion(Region region, int thickness, Pattern pattern) throws
*
* @return number of blocks affected
* @throws MaxChangedBlocksException thrown if too many blocks are changed
*
* @see #drawLine(Pattern, List, double, boolean)
*/
public int drawLine(Pattern pattern, BlockVector3 pos1, BlockVector3 pos2, double radius, boolean filled)
throws MaxChangedBlocksException {
return drawLine(pattern, ImmutableList.of(pos1, pos2), radius, filled);
}
/**
* Draws a line (out of blocks) between two or more vectors.
*
* @param pattern The block pattern used to draw the line.
* @param vectors the list of vectors to draw the line between
* @param radius The radius (thickness) of the line.
* @param filled If false, only a shell will be generated.
*
* @return number of blocks affected
* @throws MaxChangedBlocksException thrown if too many blocks are changed
*/
public int drawLine(Pattern pattern, List<BlockVector3> vectors, double radius, boolean filled)
throws MaxChangedBlocksException {
Set<BlockVector3> vset = new HashSet<>();
boolean notdrawn = true;
for (int i = 0; vectors.size() != 0 && i < vectors.size() - 1; i++) {
BlockVector3 pos1 = vectors.get(i);
BlockVector3 pos2 = vectors.get(i + 1);
int x1 = pos1.getBlockX(), y1 = pos1.getBlockY(), z1 = pos1.getBlockZ();
int x2 = pos2.getBlockX(), y2 = pos2.getBlockY(), z2 = pos2.getBlockZ();
@ -2200,10 +2222,11 @@ public int drawLine(Pattern pattern, BlockVector3 pos1, BlockVector3 pos2, doubl
if (dx + dy + dz == 0) {
vset.add(BlockVector3.at(tipx, tipy, tipz));
notdrawn = false;
continue;
}
if (Math.max(Math.max(dx, dy), dz) == dx && notdrawn) {
int dMax = Math.max(Math.max(dx, dy), dz);
if (dMax == dx) {
for (int domstep = 0; domstep <= dx; domstep++) {
tipx = x1 + domstep * (x2 - x1 > 0 ? 1 : -1);
tipy = (int) Math.round(y1 + domstep * ((double) dy) / ((double) dx) * (y2 - y1 > 0 ? 1 : -1));
@ -2211,10 +2234,7 @@ public int drawLine(Pattern pattern, BlockVector3 pos1, BlockVector3 pos2, doubl
vset.add(BlockVector3.at(tipx, tipy, tipz));
}
notdrawn = false;
}
if (Math.max(Math.max(dx, dy), dz) == dy && notdrawn) {
} else if (dMax == dy) {
for (int domstep = 0; domstep <= dy; domstep++) {
tipy = y1 + domstep * (y2 - y1 > 0 ? 1 : -1);
tipx = (int) Math.round(x1 + domstep * ((double) dx) / ((double) dy) * (x2 - x1 > 0 ? 1 : -1));
@ -2222,10 +2242,7 @@ public int drawLine(Pattern pattern, BlockVector3 pos1, BlockVector3 pos2, doubl
vset.add(BlockVector3.at(tipx, tipy, tipz));
}
notdrawn = false;
}
if (Math.max(Math.max(dx, dy), dz) == dz && notdrawn) {
} else /* if (dMax == dz) */ {
for (int domstep = 0; domstep <= dz; domstep++) {
tipz = z1 + domstep * (z2 - z1 > 0 ? 1 : -1);
tipy = (int) Math.round(y1 + domstep * ((double) dy) / ((double) dz) * (y2-y1>0 ? 1 : -1));
@ -2233,7 +2250,7 @@ public int drawLine(Pattern pattern, BlockVector3 pos1, BlockVector3 pos2, doubl
vset.add(BlockVector3.at(tipx, tipy, tipz));
}
notdrawn = false;
}
}
vset = getBallooned(vset, radius);

View File

@ -20,6 +20,7 @@
package com.sk89q.worldedit.command;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalSession;
@ -112,8 +113,8 @@ public int set(Actor actor, EditSession editSession,
@Command(
name = "/line",
desc = "Draws a line segment between cuboid selection corners",
descFooter = "Can only be used with a cuboid selection"
desc = "Draws line segments between cuboid selection corners or convex polyhedral selection vertices",
descFooter = "Can only be used with a cuboid selection or a convex polyhedral selection"
)
@CommandPermissions("worldedit.region.line")
@Logging(REGION)
@ -125,16 +126,24 @@ public int line(Actor actor, EditSession editSession,
int thickness,
@Switch(name = 'h', desc = "Generate only a shell")
boolean shell) throws WorldEditException {
if (!(region instanceof CuboidRegion)) {
actor.printError("//line only works with cuboid selections");
if (!((region instanceof CuboidRegion) || (region instanceof ConvexPolyhedralRegion))) {
actor.printError("//line only works with cuboid selections or convex polyhedral selections");
return 0;
}
checkCommandArgument(thickness >= 0, "Thickness must be >= 0");
CuboidRegion cuboidregion = (CuboidRegion) region;
BlockVector3 pos1 = cuboidregion.getPos1();
BlockVector3 pos2 = cuboidregion.getPos2();
int blocksChanged = editSession.drawLine(pattern, pos1, pos2, thickness, !shell);
List<BlockVector3> vectors;
if (region instanceof CuboidRegion) {
CuboidRegion cuboidRegion = (CuboidRegion) region;
vectors = ImmutableList.of(cuboidRegion.getPos1(), cuboidRegion.getPos2());
} else {
ConvexPolyhedralRegion convexRegion = (ConvexPolyhedralRegion) region;
vectors = ImmutableList.copyOf(convexRegion.getVertices());
}
int blocksChanged = editSession.drawLine(pattern, vectors, thickness, !shell);
actor.print(blocksChanged + " block(s) have been changed.");
return blocksChanged;