use of com.sk89q.worldedit.math.interpolation.Node in project FastAsyncWorldEdit by IntellectualSites.
the class EditSession method drawSpline.
/**
* Draws a spline (out of blocks) between specified vectors.
*
* @param pattern The block pattern used to draw the spline.
* @param nodevectors The list of vectors to draw through.
* @param tension The tension of every node.
* @param bias The bias of every node.
* @param continuity The continuity of every node.
* @param quality The quality of the spline. Must be greater than 0.
* @param radius The radius (thickness) of the spline.
* @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 drawSpline(Pattern pattern, List<BlockVector3> nodevectors, double tension, double bias, double continuity, double quality, double radius, boolean filled) throws MaxChangedBlocksException {
LocalBlockVectorSet vset = new LocalBlockVectorSet();
List<Node> nodes = new ArrayList<>(nodevectors.size());
Interpolation interpol = new KochanekBartelsInterpolation();
for (BlockVector3 nodevector : nodevectors) {
Node n = new Node(nodevector.toVector3());
n.setTension(tension);
n.setBias(bias);
n.setContinuity(continuity);
nodes.add(n);
}
interpol.setNodes(nodes);
double splinelength = interpol.arcLength(0, 1);
for (double loop = 0; loop <= 1; loop += 1D / splinelength / quality) {
BlockVector3 tipv = interpol.getPosition(loop).toBlockPoint();
if (radius == 0) {
pattern.apply(this, tipv, tipv);
changes++;
} else {
vset.add(tipv);
}
}
Set<BlockVector3> newVset;
if (radius != 0) {
newVset = getBallooned(vset, radius);
if (!filled) {
newVset = this.getHollowed(newVset);
}
return this.changes += setBlocks(newVset, pattern);
}
return changes;
}
use of com.sk89q.worldedit.math.interpolation.Node in project FastAsyncWorldEdit by IntellectualSites.
the class SurfaceSpline method build.
@Override
public void build(EditSession editSession, BlockVector3 pos, Pattern pattern, double radius) throws MaxChangedBlocksException {
int maxY = editSession.getMaxY();
int minY = editSession.getMinY();
if (path.isEmpty() || !pos.equals(path.get(path.size() - 1))) {
int max = editSession.getNearestSurfaceTerrainBlock(pos.getBlockX(), pos.getBlockZ(), pos.getBlockY(), minY, maxY);
if (max == -1) {
return;
}
path.add(BlockVector3.at(pos.getBlockX(), max, pos.getBlockZ()));
if (editSession.getActor() != null) {
editSession.getActor().print(Caption.of("fawe.worldedit.brush.spline.primary.2"));
}
return;
}
final List<Node> nodes = new ArrayList<>(path.size());
final KochanekBartelsInterpolation interpol = new KochanekBartelsInterpolation();
for (BlockVector3 nodevector : path) {
final Node n = new Node(nodevector.toVector3());
n.setTension(tension);
n.setBias(bias);
n.setContinuity(continuity);
nodes.add(n);
}
MutableBlockVector3 mutable = MutableBlockVector3.at(0, 0, 0);
interpol.setNodes(nodes);
final double splinelength = interpol.arcLength(0, 1);
LocalBlockVectorSet vset = new LocalBlockVectorSet();
for (double loop = 0; loop <= 1; loop += 1D / splinelength / quality) {
final Vector3 tipv = interpol.getPosition(loop);
final int tipx = MathMan.roundInt(tipv.getX());
final int tipz = (int) tipv.getZ();
int tipy = MathMan.roundInt(tipv.getY());
tipy = editSession.getNearestSurfaceTerrainBlock(tipx, tipz, tipy, minY, maxY, Integer.MIN_VALUE, Integer.MAX_VALUE);
if (tipy == Integer.MIN_VALUE || tipy == Integer.MAX_VALUE) {
continue;
}
if (radius == 0) {
BlockVector3 set = mutable.setComponents(tipx, tipy, tipz);
pattern.apply(editSession, set, set);
} else {
vset.add(tipx, tipy, tipz);
}
}
if (radius != 0) {
double radius2 = radius * radius;
LocalBlockVectorSet newSet = new LocalBlockVectorSet();
final int ceilrad = (int) Math.ceil(radius);
for (BlockVector3 v : vset) {
final int tipx = v.getBlockX();
final int tipz = v.getBlockZ();
for (int loopx = tipx - ceilrad; loopx <= tipx + ceilrad; loopx++) {
for (int loopz = tipz - ceilrad; loopz <= tipz + ceilrad; loopz++) {
if (MathMan.hypot2(loopx - tipx, 0, loopz - tipz) <= radius2) {
int y = editSession.getNearestSurfaceTerrainBlock(loopx, loopz, v.getBlockY(), minY, maxY, Integer.MIN_VALUE, Integer.MAX_VALUE);
if (y == Integer.MIN_VALUE || y == Integer.MAX_VALUE) {
continue;
}
newSet.add(loopx, y, loopz);
}
}
}
}
editSession.setBlocks(newSet, pattern);
}
path.clear();
if (editSession.getActor() != null) {
editSession.getActor().print(Caption.of("fawe.worldedit.brush.spline.secondary"));
}
}
use of com.sk89q.worldedit.math.interpolation.Node in project FastAsyncWorldEdit by IntellectualSites.
the class SplineBrush method build.
@Override
public void build(EditSession editSession, BlockVector3 position, Pattern pattern, double size) throws WorldEditException {
Mask mask = editSession.getMask();
if (mask == null) {
mask = new IdMask(editSession);
} else {
mask = new MaskIntersection(mask, new IdMask(editSession));
}
boolean newPos = !position.equals(this.position);
this.position = position;
if (newPos) {
if (positionSets.size() >= MAX_POINTS) {
throw FaweCache.MAX_CHECKS;
}
final ArrayList<BlockVector3> points = new ArrayList<>();
if (size > 0) {
DFSRecursiveVisitor visitor = new DFSRecursiveVisitor(mask, p -> {
points.add(p);
return true;
}, (int) size, 1);
List<BlockVector3> directions = visitor.getDirections();
for (int x = -1; x <= 1; x++) {
for (int y = -1; y <= 1; y++) {
for (int z = -1; z <= 1; z++) {
if (x != 0 || y != 0 || z != 0) {
BlockVector3 pos = BlockVector3.at(x, y, z);
if (!directions.contains(pos)) {
directions.add(pos);
}
}
}
}
}
directions.sort((o1, o2) -> (int) Math.signum(o1.lengthSq() - o2.lengthSq()));
visitor.visit(position);
Operations.completeBlindly(visitor);
if (points.size() > numSplines) {
numSplines = points.size();
}
} else {
points.add(position);
}
this.positionSets.add(points);
player.print(Caption.of("fawe.worldedit.brush.spline.primary.2"));
return;
}
if (positionSets.size() < 2) {
player.print(Caption.of("fawe.worldedit.brush.brush.spline.secondary.error"));
return;
}
List<Vector3> centroids = new ArrayList<>();
for (List<BlockVector3> points : positionSets) {
centroids.add(getCentroid(points));
}
double tension = 0;
double bias = 0;
double continuity = 0;
final List<Node> nodes = new ArrayList<>(centroids.size());
for (Vector3 nodevector : centroids) {
final Node n = new Node(nodevector);
n.setTension(tension);
n.setBias(bias);
n.setContinuity(continuity);
nodes.add(n);
}
for (int i = 0; i < numSplines; i++) {
List<BlockVector3> currentSpline = new ArrayList<>();
for (ArrayList<BlockVector3> points : positionSets) {
int listSize = points.size();
int index = (int) (i * listSize / (double) numSplines);
currentSpline.add(points.get(index));
}
editSession.drawSpline(pattern, currentSpline, 0, 0, 0, 10, 0, true);
}
player.print(Caption.of("fawe.worldedit.brush.spline.secondary"));
positionSets.clear();
numSplines = 0;
}
Aggregations