Search in sources :

Example 1 with Node

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;
}
Also used : KochanekBartelsInterpolation(com.sk89q.worldedit.math.interpolation.KochanekBartelsInterpolation) Interpolation(com.sk89q.worldedit.math.interpolation.Interpolation) LocalBlockVectorSet(com.fastasyncworldedit.core.math.LocalBlockVectorSet) Node(com.sk89q.worldedit.math.interpolation.Node) KochanekBartelsInterpolation(com.sk89q.worldedit.math.interpolation.KochanekBartelsInterpolation) ArrayList(java.util.ArrayList) MutableBlockVector3(com.fastasyncworldedit.core.math.MutableBlockVector3) BlockVector3(com.sk89q.worldedit.math.BlockVector3)

Example 2 with Node

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"));
    }
}
Also used : MutableBlockVector3(com.fastasyncworldedit.core.math.MutableBlockVector3) LocalBlockVectorSet(com.fastasyncworldedit.core.math.LocalBlockVectorSet) Node(com.sk89q.worldedit.math.interpolation.Node) KochanekBartelsInterpolation(com.sk89q.worldedit.math.interpolation.KochanekBartelsInterpolation) ArrayList(java.util.ArrayList) BlockVector3(com.sk89q.worldedit.math.BlockVector3) Vector3(com.sk89q.worldedit.math.Vector3) MutableBlockVector3(com.fastasyncworldedit.core.math.MutableBlockVector3) BlockVector3(com.sk89q.worldedit.math.BlockVector3) MutableBlockVector3(com.fastasyncworldedit.core.math.MutableBlockVector3)

Example 3 with Node

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;
}
Also used : DFSRecursiveVisitor(com.fastasyncworldedit.core.function.visitor.DFSRecursiveVisitor) MaskIntersection(com.sk89q.worldedit.function.mask.MaskIntersection) Node(com.sk89q.worldedit.math.interpolation.Node) IdMask(com.fastasyncworldedit.core.function.mask.IdMask) Mask(com.sk89q.worldedit.function.mask.Mask) ArrayList(java.util.ArrayList) BlockVector3(com.sk89q.worldedit.math.BlockVector3) Vector3(com.sk89q.worldedit.math.Vector3) MutableVector3(com.fastasyncworldedit.core.math.MutableVector3) BlockVector3(com.sk89q.worldedit.math.BlockVector3) IdMask(com.fastasyncworldedit.core.function.mask.IdMask)

Aggregations

BlockVector3 (com.sk89q.worldedit.math.BlockVector3)3 Node (com.sk89q.worldedit.math.interpolation.Node)3 ArrayList (java.util.ArrayList)3 LocalBlockVectorSet (com.fastasyncworldedit.core.math.LocalBlockVectorSet)2 MutableBlockVector3 (com.fastasyncworldedit.core.math.MutableBlockVector3)2 Vector3 (com.sk89q.worldedit.math.Vector3)2 KochanekBartelsInterpolation (com.sk89q.worldedit.math.interpolation.KochanekBartelsInterpolation)2 IdMask (com.fastasyncworldedit.core.function.mask.IdMask)1 DFSRecursiveVisitor (com.fastasyncworldedit.core.function.visitor.DFSRecursiveVisitor)1 MutableVector3 (com.fastasyncworldedit.core.math.MutableVector3)1 Mask (com.sk89q.worldedit.function.mask.Mask)1 MaskIntersection (com.sk89q.worldedit.function.mask.MaskIntersection)1 Interpolation (com.sk89q.worldedit.math.interpolation.Interpolation)1