From 9b93a5cd04fe6a6c9f3673850c96ac6caacfd9f2 Mon Sep 17 00:00:00 2001 From: cyberpwn Date: Fri, 27 Aug 2021 05:08:40 -0400 Subject: [PATCH] Move editing stuff to writer --- .../iris/engine/mantle/MantleWriter.java | 444 ++++++++++++++++++ .../com/volmit/iris/util/mantle/Mantle.java | 433 ----------------- 2 files changed, 444 insertions(+), 433 deletions(-) diff --git a/src/main/java/com/volmit/iris/engine/mantle/MantleWriter.java b/src/main/java/com/volmit/iris/engine/mantle/MantleWriter.java index b6b9482ed..1f9c6bba6 100644 --- a/src/main/java/com/volmit/iris/engine/mantle/MantleWriter.java +++ b/src/main/java/com/volmit/iris/engine/mantle/MantleWriter.java @@ -18,19 +18,31 @@ package com.volmit.iris.engine.mantle; +import com.google.common.collect.ImmutableList; import com.volmit.iris.Iris; import com.volmit.iris.core.loader.IrisData; import com.volmit.iris.engine.data.cache.Cache; +import com.volmit.iris.engine.object.basic.IrisPosition; import com.volmit.iris.engine.object.common.IObjectPlacer; import com.volmit.iris.engine.object.feature.IrisFeaturePositional; import com.volmit.iris.engine.object.tile.TileData; import com.volmit.iris.util.collection.KMap; +import com.volmit.iris.util.collection.KSet; import com.volmit.iris.util.mantle.Mantle; import com.volmit.iris.util.mantle.MantleChunk; +import com.volmit.iris.util.math.INode; +import com.volmit.iris.util.math.KochanekBartelsInterpolation; +import com.volmit.iris.util.math.PathInterpolation; import com.volmit.iris.util.matter.Matter; import lombok.Data; import org.bukkit.block.TileState; import org.bukkit.block.data.BlockData; +import org.bukkit.util.Vector; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; @Data public class MantleWriter implements IObjectPlacer { @@ -133,4 +145,436 @@ public class MantleWriter implements IObjectPlacer { public void setTile(int xx, int yy, int zz, TileData tile) { getEngineMantle().setTile(xx, yy, zz, tile); } + /** + * Set a sphere into the mantle + * + * @param cx the center x + * @param cy the center y + * @param cz the center z + * @param radius the radius of this sphere + * @param fill should it be filled? or just the outer shell? + * @param data the data to set + * @param the type of data to apply to the mantle + */ + public void setSphere(int cx, int cy, int cz, double radius, boolean fill, T data) { + setElipsoid(cx, cy, cz, radius, radius, radius, fill, data); + } + + /** + * Set an elipsoid into the mantle + * + * @param cx the center x + * @param cy the center y + * @param cz the center z + * @param rx the x radius + * @param ry the y radius + * @param rz the z radius + * @param fill should it be filled or just the outer shell? + * @param data the data to set + * @param the type of data to apply to the mantle + */ + public void setElipsoid(int cx, int cy, int cz, double rx, double ry, double rz, boolean fill, T data) { + rx += 0.5; + ry += 0.5; + rz += 0.5; + final double invRadiusX = 1 / rx; + final double invRadiusY = 1 / ry; + final double invRadiusZ = 1 / rz; + final int ceilRadiusX = (int) Math.ceil(rx); + final int ceilRadiusY = (int) Math.ceil(ry); + final int ceilRadiusZ = (int) Math.ceil(rz); + 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; + 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; + } + + if (!fill) { + if (lengthSq(nextXn, yn, zn) <= 1 && lengthSq(xn, nextYn, zn) <= 1 && lengthSq(xn, yn, nextZn) <= 1) { + continue; + } + } + + setData(x + cx, y + cy, z + cz, data); + setData(-x + cx, y + cy, z + cz, data); + setData(x + cx, -y + cy, z + cz, data); + setData(x + cx, y + cy, -z + cz, data); + setData(-x + cx, y + cy, -z + cz, data); + setData(-x + cx, -y + cy, z + cz, data); + setData(x + cx, -y + cy, -z + cz, data); + setData(-x + cx, y + cy, -z + cz, data); + setData(-x + cx, -y + cy, -z + cz, data); + } + } + } + } + + /** + * Set a cuboid of data in the mantle + * + * @param x1 the min x + * @param y1 the min y + * @param z1 the min z + * @param x2 the max x + * @param y2 the max y + * @param z2 the max z + * @param data the data to set + * @param the type of data to apply to the mantle + */ + public void setCuboid(int x1, int y1, int z1, int x2, int y2, int z2, T data) { + int j, k; + + for (int i = x1; i <= x2; i++) { + for (j = x1; j <= x2; j++) { + for (k = x1; k <= x2; k++) { + setData(i, j, k, data); + } + } + } + } + + /** + * Set a pyramid of data in the mantle + * + * @param cx the center x + * @param cy the base y + * @param cz the center z + * @param data the data to set + * @param size the size of the pyramid (width of base & height) + * @param filled should it be filled or hollow + * @param the type of data to apply to the mantle + */ + @SuppressWarnings("ConstantConditions") + public void setPyramid(int cx, int cy, int cz, T data, int size, boolean filled) { + int height = size; + + for (int y = 0; y <= height; ++y) { + size--; + for (int x = 0; x <= size; ++x) { + for (int z = 0; z <= size; ++z) { + if ((filled && z <= size && x <= size) || z == size || x == size) { + setData(x + cx, y + cy, z + cz, data); + setData(-x + cx, y + cy, z + cz, data); + setData(x + cx, y + cy, -z + cz, data); + setData(-x + cx, y + cy, -z + cz, data); + } + } + } + } + } + + /** + * Set a 3d tube spline interpolated with Kochanek Bartels + * + * @param nodevectors the vector points + * @param radius the radius + * @param filled if it should be filled or hollow + * @param data the data to set + */ + public void setSpline(List nodevectors, double radius, boolean filled, T data) { + setSpline(nodevectors, 0, 0, 0, 10, radius, filled, data); + } + + /** + * Set a 3d tube spline interpolated with Kochanek Bartels + * + * @param nodevectors the spline points + * @param tension the tension 0 + * @param bias the bias 0 + * @param continuity the continuity 0 + * @param quality the quality 10 + * @param radius the radius + * @param filled filled or hollow + * @param data the data to set + * @param the type of data to apply to the mantle + */ + public void setSpline(List nodevectors, double tension, double bias, double continuity, double quality, double radius, boolean filled, T data) { + Set vset = new KSet<>(); + List nodes = new ArrayList<>(nodevectors.size()); + PathInterpolation interpol = new KochanekBartelsInterpolation(); + + for (Vector nodevector : nodevectors) { + INode n = new INode(nodevector); + 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) { + Vector tipv = interpol.getPosition(loop); + vset.add(new IrisPosition(tipv.toBlockVector())); + } + + vset = getBallooned(vset, radius); + if (!filled) { + vset = getHollowed(vset); + } + + set(vset, data); + } + + /** + * Set a 3d line + * + * @param a the first point + * @param b the second point + * @param radius the radius + * @param filled hollow or filled? + * @param data the data + * @param the type of data to apply to the mantle + */ + public void setLine(IrisPosition a, IrisPosition b, double radius, boolean filled, T data) { + setLine(ImmutableList.of(a, b), radius, filled, data); + } + + /** + * Set lines for points + * + * @param vectors the points + * @param radius the radius + * @param filled hollow or filled? + * @param data the data to set + * @param the type of data to apply to the mantle + */ + public void setLine(List vectors, double radius, boolean filled, T data) { + Set vset = new KSet<>(); + + for (int i = 0; vectors.size() != 0 && i < vectors.size() - 1; i++) { + IrisPosition pos1 = vectors.get(i); + IrisPosition pos2 = vectors.get(i + 1); + int x1 = pos1.getX(); + int y1 = pos1.getY(); + int z1 = pos1.getZ(); + int x2 = pos2.getX(); + int y2 = pos2.getY(); + int z2 = pos2.getZ(); + int tipx = x1; + int tipy = y1; + int tipz = z1; + int dx = Math.abs(x2 - x1); + int dy = Math.abs(y2 - y1); + int dz = Math.abs(z2 - z1); + + if (dx + dy + dz == 0) { + vset.add(new IrisPosition(tipx, tipy, tipz)); + continue; + } + + 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)); + tipz = (int) Math.round(z1 + domstep * ((double) dz) / ((double) dx) * (z2 - z1 > 0 ? 1 : -1)); + + vset.add(new IrisPosition(tipx, tipy, tipz)); + } + } 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)); + tipz = (int) Math.round(z1 + domstep * ((double) dz) / ((double) dy) * (z2 - z1 > 0 ? 1 : -1)); + + vset.add(new IrisPosition(tipx, tipy, tipz)); + } + } 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)); + tipx = (int) Math.round(x1 + domstep * ((double) dx) / ((double) dz) * (x2 - x1 > 0 ? 1 : -1)); + + vset.add(new IrisPosition(tipx, tipy, tipz)); + } + } + } + + vset = getBallooned(vset, radius); + + if (!filled) { + vset = getHollowed(vset); + } + + set(vset, data); + } + + /** + * Set a cylinder in the mantle + * + * @param cx the center x + * @param cy the base y + * @param cz the center z + * @param data the data to set + * @param radius the radius + * @param height the height of the cyl + * @param filled filled or not + */ + public void setCylinder(int cx, int cy, int cz, T data, double radius, int height, boolean filled) { + setCylinder(cx, cy, cz, data, radius, radius, height, filled); + } + + /** + * Set a cylinder in the mantle + * + * @param cx the center x + * @param cy the base y + * @param cz the center z + * @param data the data to set + * @param radiusX the x radius + * @param radiusZ the z radius + * @param height the height of this cyl + * @param filled filled or hollow? + */ + public void setCylinder(int cx, int cy, int cz, T data, double radiusX, double radiusZ, int height, boolean filled) { + int affected = 0; + radiusX += 0.5; + radiusZ += 0.5; + + if (height == 0) { + return; + } else if (height < 0) { + height = -height; + cy = cy - height; + } + + if (cy < 0) { + cy = 0; + } else if (cy + height - 1 > getMantle().getWorldHeight()) { + height = getMantle().getWorldHeight() - cy + 1; + } + + final double invRadiusX = 1 / radiusX; + final double invRadiusZ = 1 / radiusZ; + final int ceilRadiusX = (int) Math.ceil(radiusX); + 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 nextZn = 0; + for (int z = 0; z <= ceilRadiusZ; ++z) { + final double zn = nextZn; + nextZn = (z + 1) * invRadiusZ; + double distanceSq = lengthSq(xn, zn); + + if (distanceSq > 1) { + if (z == 0) { + break forX; + } + + break; + } + + if (!filled) { + if (lengthSq(nextXn, zn) <= 1 && lengthSq(xn, nextZn) <= 1) { + continue; + } + } + + for (int y = 0; y < height; ++y) { + setData(cx + x, cy + y, cz + z, data); + setData(cx + -x, cy + y, cz + z, data); + setData(cx + x, cy + y, cz + -z, data); + setData(cx + -x, cy + y, cz + -z, data); + } + } + } + } + + public void set(IrisPosition pos, T data) { + setData(pos.getX(), pos.getY(), pos.getZ(), data); + } + + public void set(List positions, T data) { + for (IrisPosition i : positions) { + set(i, data); + } + } + + public void set(Set positions, T data) { + for (IrisPosition i : positions) { + set(i, data); + } + } + + private static Set getBallooned(Set vset, double radius) { + Set returnset = new HashSet<>(); + int ceilrad = (int) Math.ceil(radius); + + for (IrisPosition v : vset) { + int tipx = v.getX(); + int tipy = v.getY(); + int tipz = v.getZ(); + + for (int loopx = tipx - ceilrad; loopx <= tipx + ceilrad; loopx++) { + for (int loopy = tipy - ceilrad; loopy <= tipy + ceilrad; loopy++) { + for (int loopz = tipz - ceilrad; loopz <= tipz + ceilrad; loopz++) { + if (hypot(loopx - tipx, loopy - tipy, loopz - tipz) <= radius) { + returnset.add(new IrisPosition(loopx, loopy, loopz)); + } + } + } + } + } + return returnset; + } + + private static Set getHollowed(Set vset) { + Set returnset = new KSet<>(); + for (IrisPosition v : vset) { + double x = v.getX(); + double y = v.getY(); + double z = v.getZ(); + if (!(vset.contains(new IrisPosition(x + 1, y, z)) + && vset.contains(new IrisPosition(x - 1, y, z)) + && vset.contains(new IrisPosition(x, y + 1, z)) + && vset.contains(new IrisPosition(x, y - 1, z)) + && vset.contains(new IrisPosition(x, y, z + 1)) + && vset.contains(new IrisPosition(x, y, z - 1)))) { + returnset.add(v); + } + } + return returnset; + } + + private static double hypot(double... pars) { + double sum = 0; + for (double d : pars) { + sum += Math.pow(d, 2); + } + return Math.sqrt(sum); + } + + private static double lengthSq(double x, double y, double z) { + return (x * x) + (y * y) + (z * z); + } + + private static double lengthSq(double x, double z) { + return (x * x) + (z * z); + } } diff --git a/src/main/java/com/volmit/iris/util/mantle/Mantle.java b/src/main/java/com/volmit/iris/util/mantle/Mantle.java index 5f9139150..092a1b6c7 100644 --- a/src/main/java/com/volmit/iris/util/mantle/Mantle.java +++ b/src/main/java/com/volmit/iris/util/mantle/Mantle.java @@ -499,439 +499,6 @@ public class Mantle { } - /** - * Set a sphere into the mantle - * - * @param cx the center x - * @param cy the center y - * @param cz the center z - * @param radius the radius of this sphere - * @param fill should it be filled? or just the outer shell? - * @param data the data to set - * @param the type of data to apply to the mantle - */ - public void setSphere(int cx, int cy, int cz, double radius, boolean fill, T data) { - setElipsoid(cx, cy, cz, radius, radius, radius, fill, data); - } - - /** - * Set an elipsoid into the mantle - * - * @param cx the center x - * @param cy the center y - * @param cz the center z - * @param rx the x radius - * @param ry the y radius - * @param rz the z radius - * @param fill should it be filled or just the outer shell? - * @param data the data to set - * @param the type of data to apply to the mantle - */ - public void setElipsoid(int cx, int cy, int cz, double rx, double ry, double rz, boolean fill, T data) { - rx += 0.5; - ry += 0.5; - rz += 0.5; - final double invRadiusX = 1 / rx; - final double invRadiusY = 1 / ry; - final double invRadiusZ = 1 / rz; - final int ceilRadiusX = (int) Math.ceil(rx); - final int ceilRadiusY = (int) Math.ceil(ry); - final int ceilRadiusZ = (int) Math.ceil(rz); - 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; - 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; - } - - if (!fill) { - if (lengthSq(nextXn, yn, zn) <= 1 && lengthSq(xn, nextYn, zn) <= 1 && lengthSq(xn, yn, nextZn) <= 1) { - continue; - } - } - - set(x + cx, y + cy, z + cz, data); - set(-x + cx, y + cy, z + cz, data); - set(x + cx, -y + cy, z + cz, data); - set(x + cx, y + cy, -z + cz, data); - set(-x + cx, y + cy, -z + cz, data); - set(-x + cx, -y + cy, z + cz, data); - set(x + cx, -y + cy, -z + cz, data); - set(-x + cx, y + cy, -z + cz, data); - set(-x + cx, -y + cy, -z + cz, data); - } - } - } - } - - /** - * Set a cuboid of data in the mantle - * - * @param x1 the min x - * @param y1 the min y - * @param z1 the min z - * @param x2 the max x - * @param y2 the max y - * @param z2 the max z - * @param data the data to set - * @param the type of data to apply to the mantle - */ - public void setCuboid(int x1, int y1, int z1, int x2, int y2, int z2, T data) { - int j, k; - - for (int i = x1; i <= x2; i++) { - for (j = x1; j <= x2; j++) { - for (k = x1; k <= x2; k++) { - set(i, j, k, data); - } - } - } - } - - /** - * Set a pyramid of data in the mantle - * - * @param cx the center x - * @param cy the base y - * @param cz the center z - * @param data the data to set - * @param size the size of the pyramid (width of base & height) - * @param filled should it be filled or hollow - * @param the type of data to apply to the mantle - */ - @SuppressWarnings("ConstantConditions") - public void setPyramid(int cx, int cy, int cz, T data, int size, boolean filled) { - int height = size; - - for (int y = 0; y <= height; ++y) { - size--; - for (int x = 0; x <= size; ++x) { - for (int z = 0; z <= size; ++z) { - if ((filled && z <= size && x <= size) || z == size || x == size) { - set(x + cx, y + cy, z + cz, data); - set(-x + cx, y + cy, z + cz, data); - set(x + cx, y + cy, -z + cz, data); - set(-x + cx, y + cy, -z + cz, data); - } - } - } - } - } - - /** - * Set a 3d tube spline interpolated with Kochanek Bartels - * - * @param nodevectors the vector points - * @param radius the radius - * @param filled if it should be filled or hollow - * @param data the data to set - */ - public void setSpline(List nodevectors, double radius, boolean filled, T data) { - setSpline(nodevectors, 0, 0, 0, 10, radius, filled, data); - } - - /** - * Set a 3d tube spline interpolated with Kochanek Bartels - * - * @param nodevectors the spline points - * @param tension the tension 0 - * @param bias the bias 0 - * @param continuity the continuity 0 - * @param quality the quality 10 - * @param radius the radius - * @param filled filled or hollow - * @param data the data to set - * @param the type of data to apply to the mantle - */ - public void setSpline(List nodevectors, double tension, double bias, double continuity, double quality, double radius, boolean filled, T data) { - Set vset = new KSet<>(); - List nodes = new ArrayList<>(nodevectors.size()); - PathInterpolation interpol = new KochanekBartelsInterpolation(); - - for (Vector nodevector : nodevectors) { - INode n = new INode(nodevector); - 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) { - Vector tipv = interpol.getPosition(loop); - vset.add(new IrisPosition(tipv.toBlockVector())); - } - - vset = getBallooned(vset, radius); - if (!filled) { - vset = getHollowed(vset); - } - - set(vset, data); - } - - /** - * Set a 3d line - * - * @param a the first point - * @param b the second point - * @param radius the radius - * @param filled hollow or filled? - * @param data the data - * @param the type of data to apply to the mantle - */ - public void setLine(IrisPosition a, IrisPosition b, double radius, boolean filled, T data) { - setLine(ImmutableList.of(a, b), radius, filled, data); - } - - /** - * Set lines for points - * - * @param vectors the points - * @param radius the radius - * @param filled hollow or filled? - * @param data the data to set - * @param the type of data to apply to the mantle - */ - public void setLine(List vectors, double radius, boolean filled, T data) { - Set vset = new KSet<>(); - - for (int i = 0; vectors.size() != 0 && i < vectors.size() - 1; i++) { - IrisPosition pos1 = vectors.get(i); - IrisPosition pos2 = vectors.get(i + 1); - int x1 = pos1.getX(); - int y1 = pos1.getY(); - int z1 = pos1.getZ(); - int x2 = pos2.getX(); - int y2 = pos2.getY(); - int z2 = pos2.getZ(); - int tipx = x1; - int tipy = y1; - int tipz = z1; - int dx = Math.abs(x2 - x1); - int dy = Math.abs(y2 - y1); - int dz = Math.abs(z2 - z1); - - if (dx + dy + dz == 0) { - vset.add(new IrisPosition(tipx, tipy, tipz)); - continue; - } - - 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)); - tipz = (int) Math.round(z1 + domstep * ((double) dz) / ((double) dx) * (z2 - z1 > 0 ? 1 : -1)); - - vset.add(new IrisPosition(tipx, tipy, tipz)); - } - } 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)); - tipz = (int) Math.round(z1 + domstep * ((double) dz) / ((double) dy) * (z2 - z1 > 0 ? 1 : -1)); - - vset.add(new IrisPosition(tipx, tipy, tipz)); - } - } 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)); - tipx = (int) Math.round(x1 + domstep * ((double) dx) / ((double) dz) * (x2 - x1 > 0 ? 1 : -1)); - - vset.add(new IrisPosition(tipx, tipy, tipz)); - } - } - } - - vset = getBallooned(vset, radius); - - if (!filled) { - vset = getHollowed(vset); - } - - set(vset, data); - } - - /** - * Set a cylinder in the mantle - * - * @param cx the center x - * @param cy the base y - * @param cz the center z - * @param data the data to set - * @param radius the radius - * @param height the height of the cyl - * @param filled filled or not - */ - public void setCylinder(int cx, int cy, int cz, T data, double radius, int height, boolean filled) { - setCylinder(cx, cy, cz, data, radius, radius, height, filled); - } - - /** - * Set a cylinder in the mantle - * - * @param cx the center x - * @param cy the base y - * @param cz the center z - * @param data the data to set - * @param radiusX the x radius - * @param radiusZ the z radius - * @param height the height of this cyl - * @param filled filled or hollow? - */ - public void setCylinder(int cx, int cy, int cz, T data, double radiusX, double radiusZ, int height, boolean filled) { - int affected = 0; - radiusX += 0.5; - radiusZ += 0.5; - - if (height == 0) { - return; - } else if (height < 0) { - height = -height; - cy = cy - height; - } - - if (cy < 0) { - cy = 0; - } else if (cy + height - 1 > worldHeight) { - height = worldHeight - cy + 1; - } - - final double invRadiusX = 1 / radiusX; - final double invRadiusZ = 1 / radiusZ; - final int ceilRadiusX = (int) Math.ceil(radiusX); - 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 nextZn = 0; - for (int z = 0; z <= ceilRadiusZ; ++z) { - final double zn = nextZn; - nextZn = (z + 1) * invRadiusZ; - double distanceSq = lengthSq(xn, zn); - - if (distanceSq > 1) { - if (z == 0) { - break forX; - } - - break; - } - - if (!filled) { - if (lengthSq(nextXn, zn) <= 1 && lengthSq(xn, nextZn) <= 1) { - continue; - } - } - - for (int y = 0; y < height; ++y) { - set(cx + x, cy + y, cz + z, data); - set(cx + -x, cy + y, cz + z, data); - set(cx + x, cy + y, cz + -z, data); - set(cx + -x, cy + y, cz + -z, data); - } - } - } - } - - public void set(IrisPosition pos, T data) { - set(pos.getX(), pos.getY(), pos.getZ(), data); - } - - public void set(List positions, T data) { - for (IrisPosition i : positions) { - set(i, data); - } - } - - public void set(Set positions, T data) { - for (IrisPosition i : positions) { - set(i, data); - } - } - - private static Set getBallooned(Set vset, double radius) { - Set returnset = new HashSet<>(); - int ceilrad = (int) Math.ceil(radius); - - for (IrisPosition v : vset) { - int tipx = v.getX(); - int tipy = v.getY(); - int tipz = v.getZ(); - - for (int loopx = tipx - ceilrad; loopx <= tipx + ceilrad; loopx++) { - for (int loopy = tipy - ceilrad; loopy <= tipy + ceilrad; loopy++) { - for (int loopz = tipz - ceilrad; loopz <= tipz + ceilrad; loopz++) { - if (hypot(loopx - tipx, loopy - tipy, loopz - tipz) <= radius) { - returnset.add(new IrisPosition(loopx, loopy, loopz)); - } - } - } - } - } - return returnset; - } - - private static Set getHollowed(Set vset) { - Set returnset = new KSet<>(); - for (IrisPosition v : vset) { - double x = v.getX(); - double y = v.getY(); - double z = v.getZ(); - if (!(vset.contains(new IrisPosition(x + 1, y, z)) - && vset.contains(new IrisPosition(x - 1, y, z)) - && vset.contains(new IrisPosition(x, y + 1, z)) - && vset.contains(new IrisPosition(x, y - 1, z)) - && vset.contains(new IrisPosition(x, y, z + 1)) - && vset.contains(new IrisPosition(x, y, z - 1)))) { - returnset.add(v); - } - } - return returnset; - } - - private static double hypot(double... pars) { - double sum = 0; - for (double d : pars) { - sum += Math.pow(d, 2); - } - return Math.sqrt(sum); - } - - private static double lengthSq(double x, double y, double z) { - return (x * x) + (y * y) + (z * z); - } - - private static double lengthSq(double x, double z) { - return (x * x) + (z * z); - } - public int getWorldHeight() { return worldHeight; }