Update BukkitImplLoader

This commit is contained in:
MattBDev
2020-08-24 21:20:18 -04:00
parent fd8cf1ebba
commit 75a18b9d5b
45 changed files with 5618 additions and 5626 deletions

View File

@ -1,250 +1,250 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.regions;
import com.boydti.fawe.object.collection.BlockVectorSet;
import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.math.Vector3;
import com.sk89q.worldedit.regions.iterator.RegionIterator;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.storage.ChunkStore;
import java.util.AbstractSet;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.Set;
public abstract class AbstractRegion extends AbstractSet<BlockVector3> implements Region {
protected World world;
public AbstractRegion(World world) {
this.world = world;
}
@Override
public int size() {
return com.google.common.primitives.Ints.saturatedCast(getVolume());
}
@Override
public Vector3 getCenter() {
return getMinimumPoint().add(getMaximumPoint()).toVector3().divide(2);
}
/**
* Get the iterator.
*
* @return iterator of points inside the region
*/
@Override
public Iterator<BlockVector3> iterator() {
return new RegionIterator(this);
}
@Override
public World getWorld() {
return world;
}
@Override
public void setWorld(World world) {
this.world = world;
}
@Override
public void shift(BlockVector3 change) throws RegionOperationException {
expand(change);
contract(change);
}
@Override
public AbstractRegion clone() {
try {
return (AbstractRegion) super.clone();
} catch (CloneNotSupportedException exc) {
return null;
}
}
@Override
public List<BlockVector2> polygonize(int maxPoints) {
if (maxPoints >= 0 && maxPoints < 4) {
throw new IllegalArgumentException("Cannot polygonize an AbstractRegion with no overridden polygonize method into less than 4 points.");
}
final BlockVector3 min = getMinimumPoint();
final BlockVector3 max = getMaximumPoint();
final List<BlockVector2> points = new ArrayList<>(4);
points.add(BlockVector2.at(min.getX(), min.getZ()));
points.add(BlockVector2.at(min.getX(), max.getZ()));
points.add(BlockVector2.at(max.getX(), max.getZ()));
points.add(BlockVector2.at(max.getX(), min.getZ()));
return points;
}
@Override
public long getVolume() {
BlockVector3 min = getMinimumPoint();
BlockVector3 max = getMaximumPoint();
return (max.getX() - min.getX() + 1L)
* (max.getY() - min.getY() + 1L)
* (max.getZ() - min.getZ() + 1L);
}
/**
* Get X-size.
*
* @return width
*/
@Override
public int getWidth() {
BlockVector3 min = getMinimumPoint();
BlockVector3 max = getMaximumPoint();
return max.getX() - min.getX() + 1;
}
/**
* Get Y-size.
*
* @return height
*/
@Override
public int getHeight() {
BlockVector3 min = getMinimumPoint();
BlockVector3 max = getMaximumPoint();
return max.getY() - min.getY() + 1;
}
/**
* Get Z-size.
*
* @return length
*/
@Override
public int getLength() {
BlockVector3 min = getMinimumPoint();
BlockVector3 max = getMaximumPoint();
return max.getZ() - min.getZ() + 1;
}
/**
* Get a list of chunks.
*
* @return a set of chunks
*/
@Override
public Set<BlockVector2> getChunks() {
final Set<BlockVector2> chunks = new HashSet<>();
final BlockVector3 minBlock = getMinimumPoint();
final BlockVector3 maxBlock = getMaximumPoint();
final BlockVector2 min = BlockVector2.at(minBlock.getX() >> 4, minBlock.getZ() >> 4);
final BlockVector2 max = BlockVector2.at(maxBlock.getX() >> 4, maxBlock.getZ() >> 4);
for (int X = min.getBlockX(); X <= max.getBlockX(); ++X) {
for (int Z = min.getBlockZ(); Z <= max.getBlockZ(); ++Z) {
if (containsChunk(X, Z)) {
chunks.add(BlockVector2.at(X, Z));
}
}
}
return chunks;
}
@Override
public Set<BlockVector3> getChunkCubes() {
final Set<BlockVector3> chunks = new BlockVectorSet();
final BlockVector3 min = getMinimumPoint();
final BlockVector3 max = getMaximumPoint();
for (int x = min.getBlockX(); x <= max.getBlockX(); ++x) {
for (int y = min.getBlockY(); y <= max.getBlockY(); ++y) {
for (int z = min.getBlockZ(); z <= max.getBlockZ(); ++z) {
if (!contains(BlockVector3.at(x, y, z))) {
continue;
}
chunks.add(BlockVector3.at(
x >> ChunkStore.CHUNK_SHIFTS,
y >> ChunkStore.CHUNK_SHIFTS,
z >> ChunkStore.CHUNK_SHIFTS
));
}
}
}
return chunks;
}
// Sub-class utilities
protected final int getWorldMinY() {
return world == null ? 0 : world.getMinY();
}
protected final int getWorldMaxY() {
return world == null ? 255 : world.getMaxY();
}
@Override
public int hashCode() {
int worldHash = this.world == null ? 7 : this.world.hashCode();
int result = worldHash ^ (worldHash >>> 32);
result = 31 * result + this.getMinimumPoint().hashCode();
result = 31 * result + this.getMaximumPoint().hashCode();
result = (int) (31 * result + this.getVolume());
return result;
}
@Override
public boolean equals(Object o) {
if (o == this) {
return true;
}
if (!(o instanceof Region)) {
return false;
}
Region region = ((Region) o);
if (Objects.equals(this.getWorld(), region.getWorld())
&& this.getMinimumPoint().equals(region.getMinimumPoint())
&& this.getMaximumPoint().equals(region.getMaximumPoint())
&& this.getVolume() == region.getVolume()) {
return true;
}
return false;
}
}
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.regions;
import com.boydti.fawe.object.collection.BlockVectorSet;
import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.math.Vector3;
import com.sk89q.worldedit.regions.iterator.RegionIterator;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.storage.ChunkStore;
import java.util.AbstractSet;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.Set;
public abstract class AbstractRegion extends AbstractSet<BlockVector3> implements Region {
protected World world;
public AbstractRegion(World world) {
this.world = world;
}
@Override
public int size() {
return com.google.common.primitives.Ints.saturatedCast(getVolume());
}
@Override
public Vector3 getCenter() {
return getMinimumPoint().add(getMaximumPoint()).toVector3().divide(2);
}
/**
* Get the iterator.
*
* @return iterator of points inside the region
*/
@Override
public Iterator<BlockVector3> iterator() {
return new RegionIterator(this);
}
@Override
public World getWorld() {
return world;
}
@Override
public void setWorld(World world) {
this.world = world;
}
@Override
public void shift(BlockVector3 change) throws RegionOperationException {
expand(change);
contract(change);
}
@Override
public AbstractRegion clone() {
try {
return (AbstractRegion) super.clone();
} catch (CloneNotSupportedException exc) {
return null;
}
}
@Override
public List<BlockVector2> polygonize(int maxPoints) {
if (maxPoints >= 0 && maxPoints < 4) {
throw new IllegalArgumentException("Cannot polygonize an AbstractRegion with no overridden polygonize method into less than 4 points.");
}
final BlockVector3 min = getMinimumPoint();
final BlockVector3 max = getMaximumPoint();
final List<BlockVector2> points = new ArrayList<>(4);
points.add(BlockVector2.at(min.getX(), min.getZ()));
points.add(BlockVector2.at(min.getX(), max.getZ()));
points.add(BlockVector2.at(max.getX(), max.getZ()));
points.add(BlockVector2.at(max.getX(), min.getZ()));
return points;
}
@Override
public long getVolume() {
BlockVector3 min = getMinimumPoint();
BlockVector3 max = getMaximumPoint();
return (max.getX() - min.getX() + 1L)
* (max.getY() - min.getY() + 1L)
* (max.getZ() - min.getZ() + 1L);
}
/**
* Get X-size.
*
* @return width
*/
@Override
public int getWidth() {
BlockVector3 min = getMinimumPoint();
BlockVector3 max = getMaximumPoint();
return max.getX() - min.getX() + 1;
}
/**
* Get Y-size.
*
* @return height
*/
@Override
public int getHeight() {
BlockVector3 min = getMinimumPoint();
BlockVector3 max = getMaximumPoint();
return max.getY() - min.getY() + 1;
}
/**
* Get Z-size.
*
* @return length
*/
@Override
public int getLength() {
BlockVector3 min = getMinimumPoint();
BlockVector3 max = getMaximumPoint();
return max.getZ() - min.getZ() + 1;
}
/**
* Get a list of chunks.
*
* @return a set of chunks
*/
@Override
public Set<BlockVector2> getChunks() {
final Set<BlockVector2> chunks = new HashSet<>();
final BlockVector3 minBlock = getMinimumPoint();
final BlockVector3 maxBlock = getMaximumPoint();
final BlockVector2 min = BlockVector2.at(minBlock.getX() >> 4, minBlock.getZ() >> 4);
final BlockVector2 max = BlockVector2.at(maxBlock.getX() >> 4, maxBlock.getZ() >> 4);
for (int X = min.getBlockX(); X <= max.getBlockX(); ++X) {
for (int Z = min.getBlockZ(); Z <= max.getBlockZ(); ++Z) {
if (containsChunk(X, Z)) {
chunks.add(BlockVector2.at(X, Z));
}
}
}
return chunks;
}
@Override
public Set<BlockVector3> getChunkCubes() {
final Set<BlockVector3> chunks = new BlockVectorSet();
final BlockVector3 min = getMinimumPoint();
final BlockVector3 max = getMaximumPoint();
for (int x = min.getBlockX(); x <= max.getBlockX(); ++x) {
for (int y = min.getBlockY(); y <= max.getBlockY(); ++y) {
for (int z = min.getBlockZ(); z <= max.getBlockZ(); ++z) {
if (!contains(BlockVector3.at(x, y, z))) {
continue;
}
chunks.add(BlockVector3.at(
x >> ChunkStore.CHUNK_SHIFTS,
y >> ChunkStore.CHUNK_SHIFTS,
z >> ChunkStore.CHUNK_SHIFTS
));
}
}
}
return chunks;
}
// Sub-class utilities
protected final int getWorldMinY() {
return world == null ? 0 : world.getMinY();
}
protected final int getWorldMaxY() {
return world == null ? 255 : world.getMaxY();
}
@Override
public int hashCode() {
int worldHash = this.world == null ? 7 : this.world.hashCode();
int result = worldHash ^ (worldHash >>> 32);
result = 31 * result + this.getMinimumPoint().hashCode();
result = 31 * result + this.getMaximumPoint().hashCode();
result = (int) (31 * result + this.getVolume());
return result;
}
@Override
public boolean equals(Object o) {
if (o == this) {
return true;
}
if (!(o instanceof Region)) {
return false;
}
Region region = ((Region) o);
if (Objects.equals(this.getWorld(), region.getWorld())
&& this.getMinimumPoint().equals(region.getMinimumPoint())
&& this.getMaximumPoint().equals(region.getMaximumPoint())
&& this.getVolume() == region.getVolume()) {
return true;
}
return false;
}
}

View File

@ -1,336 +1,336 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.regions;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.math.Vector3;
import com.sk89q.worldedit.regions.polyhedron.Edge;
import com.sk89q.worldedit.regions.polyhedron.Triangle;
import com.sk89q.worldedit.world.World;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import javax.annotation.Nullable;
import static com.google.common.base.Preconditions.checkNotNull;
public class ConvexPolyhedralRegion extends AbstractRegion {
/**
* Vertices that are contained in the convex hull.
*/
private final Set<BlockVector3> vertices = new LinkedHashSet<>();
/**
* Triangles that form the convex hull.
*/
private final List<Triangle> triangles = new ArrayList<>();
/**
* Vertices that are coplanar to the first 3 vertices.
*/
private final Set<BlockVector3> vertexBacklog = new LinkedHashSet<>();
/**
* Minimum point of the axis-aligned bounding box.
*/
private BlockVector3 minimumPoint;
/**
* Maximum point of the axis-aligned bounding box.
*/
private BlockVector3 maximumPoint;
/**
* Accumulator for the barycenter of the polyhedron. Divide by vertices.size() to get the actual center.
*/
private BlockVector3 centerAccum = BlockVector3.ZERO;
/**
* The last triangle that caused a {@link #contains(BlockVector3)}} to classify a point as "outside". Used for optimization.
*/
private Triangle lastTriangle;
/**
* Constructs an empty mesh, containing no vertices or triangles.
*
* @param world the world
*/
public ConvexPolyhedralRegion(@Nullable World world) {
super(world);
}
/**
* Constructs an independent copy of the given region.
*
* @param region the region to copy
*/
public ConvexPolyhedralRegion(ConvexPolyhedralRegion region) {
this(region.world);
vertices.addAll(region.vertices);
triangles.addAll(region.triangles);
vertexBacklog.addAll(region.vertexBacklog);
minimumPoint = region.minimumPoint;
maximumPoint = region.maximumPoint;
centerAccum = region.centerAccum;
lastTriangle = region.lastTriangle;
}
/**
* Clears the region, removing all vertices and triangles.
*/
public void clear() {
vertices.clear();
triangles.clear();
vertexBacklog.clear();
minimumPoint = null;
maximumPoint = null;
centerAccum = BlockVector3.ZERO;
lastTriangle = null;
}
/**
* Add a vertex to the region.
*
* @param vertex the vertex
* @return true, if something changed.
*/
public boolean addVertex(BlockVector3 vertex) {
checkNotNull(vertex);
lastTriangle = null; // Probably not necessary
if (vertices.contains(vertex)) {
return false;
}
Vector3 vertexD = vertex.toVector3();
if (vertices.size() == 3) {
if (vertexBacklog.contains(vertex)) {
return false;
}
if (containsRaw(vertexD)) {
return vertexBacklog.add(vertex);
}
}
vertices.add(vertex);
centerAccum = centerAccum.add(vertex);
if (minimumPoint == null) {
minimumPoint = maximumPoint = vertex;
} else {
minimumPoint = minimumPoint.getMinimum(vertex);
maximumPoint = maximumPoint.getMaximum(vertex);
}
switch (vertices.size()) {
case 0:
case 1:
case 2:
// Incomplete, can't make a mesh yet
return true;
case 3:
// Generate minimal mesh to start from
final BlockVector3[] v = vertices.toArray(new BlockVector3[0]);
triangles.add((new Triangle(v[0].toVector3(), v[1].toVector3(), v[2].toVector3())));
triangles.add((new Triangle(v[0].toVector3(), v[2].toVector3(), v[1].toVector3())));
return true;
default:
break;
}
// Look for triangles that face the vertex and remove them
final Set<Edge> borderEdges = new LinkedHashSet<>();
for (Iterator<Triangle> it = triangles.iterator(); it.hasNext(); ) {
final Triangle triangle = it.next();
// If the triangle can't be seen, it's not relevant
if (!triangle.above(vertexD)) {
continue;
}
// Remove the triangle from the mesh
it.remove();
// ...and remember its edges
for (int i = 0; i < 3; ++i) {
final Edge edge = triangle.getEdge(i);
if (borderEdges.remove(edge)) {
continue;
}
borderEdges.add(edge);
}
}
// Add triangles between the remembered edges and the new vertex.
for (Edge edge : borderEdges) {
triangles.add(edge.createTriangle(vertexD));
}
if (!vertexBacklog.isEmpty()) {
// Remove the new vertex
vertices.remove(vertex);
// Clone, clear and work through the backlog
final List<BlockVector3> vertexBacklog2 = new ArrayList<>(vertexBacklog);
vertexBacklog.clear();
for (BlockVector3 vertex2 : vertexBacklog2) {
addVertex(vertex2);
}
// Re-add the new vertex after the backlog.
vertices.add(vertex);
}
return true;
}
public boolean isDefined() {
return !triangles.isEmpty();
}
@Override
public BlockVector3 getMinimumPoint() {
return minimumPoint;
}
@Override
public BlockVector3 getMaximumPoint() {
return maximumPoint;
}
@Override
public Vector3 getCenter() {
return centerAccum.toVector3().divide(vertices.size());
}
@Override
public void expand(BlockVector3... changes) throws RegionOperationException {
}
@Override
public void contract(BlockVector3... changes) throws RegionOperationException {
}
@Override
public void shift(BlockVector3 change) throws RegionOperationException {
Vector3 vec = change.toVector3();
shiftCollection(vertices, change);
shiftCollection(vertexBacklog, change);
for (int i = 0; i < triangles.size(); ++i) {
final Triangle triangle = triangles.get(i);
final Vector3 v0 = vec.add(triangle.getVertex(0));
final Vector3 v1 = vec.add(triangle.getVertex(1));
final Vector3 v2 = vec.add(triangle.getVertex(2));
triangles.set(i, new Triangle(v0, v1, v2));
}
minimumPoint = change.add(minimumPoint);
maximumPoint = change.add(maximumPoint);
centerAccum = change.multiply(vertices.size()).add(centerAccum);
lastTriangle = null;
}
private static void shiftCollection(Collection<BlockVector3> collection, BlockVector3 change) {
final List<BlockVector3> tmp = new ArrayList<>(collection);
collection.clear();
for (BlockVector3 vertex : tmp) {
collection.add(change.add(vertex));
}
}
@Override
public boolean contains(BlockVector3 position) {
if (!isDefined()) {
return false;
}
final BlockVector3 min = getMinimumPoint();
final BlockVector3 max = getMaximumPoint();
if (!position.containedWithin(min, max)) {
return false;
}
return containsRaw(position.toVector3());
}
private boolean containsRaw(Vector3 pt) {
if (lastTriangle != null && lastTriangle.above(pt)) {
return false;
}
for (Triangle triangle : triangles) {
if (lastTriangle == triangle) {
continue;
}
if (triangle.above(pt)) {
lastTriangle = triangle;
return false;
}
}
return true;
}
public Collection<BlockVector3> getVertices() {
if (vertexBacklog.isEmpty()) {
return vertices;
}
final List<BlockVector3> ret = new ArrayList<>(vertices);
ret.addAll(vertexBacklog);
return ret;
}
public Collection<Triangle> getTriangles() {
return triangles;
}
@Override
public AbstractRegion clone() {
return new ConvexPolyhedralRegion(this);
}
@Override
public boolean containsEntireCuboid(int bx, int tx, int by, int ty, int bz, int tz) {
return false;
}
}
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.regions;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.math.Vector3;
import com.sk89q.worldedit.regions.polyhedron.Edge;
import com.sk89q.worldedit.regions.polyhedron.Triangle;
import com.sk89q.worldedit.world.World;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import javax.annotation.Nullable;
import static com.google.common.base.Preconditions.checkNotNull;
public class ConvexPolyhedralRegion extends AbstractRegion {
/**
* Vertices that are contained in the convex hull.
*/
private final Set<BlockVector3> vertices = new LinkedHashSet<>();
/**
* Triangles that form the convex hull.
*/
private final List<Triangle> triangles = new ArrayList<>();
/**
* Vertices that are coplanar to the first 3 vertices.
*/
private final Set<BlockVector3> vertexBacklog = new LinkedHashSet<>();
/**
* Minimum point of the axis-aligned bounding box.
*/
private BlockVector3 minimumPoint;
/**
* Maximum point of the axis-aligned bounding box.
*/
private BlockVector3 maximumPoint;
/**
* Accumulator for the barycenter of the polyhedron. Divide by vertices.size() to get the actual center.
*/
private BlockVector3 centerAccum = BlockVector3.ZERO;
/**
* The last triangle that caused a {@link #contains(BlockVector3)}} to classify a point as "outside". Used for optimization.
*/
private Triangle lastTriangle;
/**
* Constructs an empty mesh, containing no vertices or triangles.
*
* @param world the world
*/
public ConvexPolyhedralRegion(@Nullable World world) {
super(world);
}
/**
* Constructs an independent copy of the given region.
*
* @param region the region to copy
*/
public ConvexPolyhedralRegion(ConvexPolyhedralRegion region) {
this(region.world);
vertices.addAll(region.vertices);
triangles.addAll(region.triangles);
vertexBacklog.addAll(region.vertexBacklog);
minimumPoint = region.minimumPoint;
maximumPoint = region.maximumPoint;
centerAccum = region.centerAccum;
lastTriangle = region.lastTriangle;
}
/**
* Clears the region, removing all vertices and triangles.
*/
public void clear() {
vertices.clear();
triangles.clear();
vertexBacklog.clear();
minimumPoint = null;
maximumPoint = null;
centerAccum = BlockVector3.ZERO;
lastTriangle = null;
}
/**
* Add a vertex to the region.
*
* @param vertex the vertex
* @return true, if something changed.
*/
public boolean addVertex(BlockVector3 vertex) {
checkNotNull(vertex);
lastTriangle = null; // Probably not necessary
if (vertices.contains(vertex)) {
return false;
}
Vector3 vertexD = vertex.toVector3();
if (vertices.size() == 3) {
if (vertexBacklog.contains(vertex)) {
return false;
}
if (containsRaw(vertexD)) {
return vertexBacklog.add(vertex);
}
}
vertices.add(vertex);
centerAccum = centerAccum.add(vertex);
if (minimumPoint == null) {
minimumPoint = maximumPoint = vertex;
} else {
minimumPoint = minimumPoint.getMinimum(vertex);
maximumPoint = maximumPoint.getMaximum(vertex);
}
switch (vertices.size()) {
case 0:
case 1:
case 2:
// Incomplete, can't make a mesh yet
return true;
case 3:
// Generate minimal mesh to start from
final BlockVector3[] v = vertices.toArray(new BlockVector3[0]);
triangles.add((new Triangle(v[0].toVector3(), v[1].toVector3(), v[2].toVector3())));
triangles.add((new Triangle(v[0].toVector3(), v[2].toVector3(), v[1].toVector3())));
return true;
default:
break;
}
// Look for triangles that face the vertex and remove them
final Set<Edge> borderEdges = new LinkedHashSet<>();
for (Iterator<Triangle> it = triangles.iterator(); it.hasNext(); ) {
final Triangle triangle = it.next();
// If the triangle can't be seen, it's not relevant
if (!triangle.above(vertexD)) {
continue;
}
// Remove the triangle from the mesh
it.remove();
// ...and remember its edges
for (int i = 0; i < 3; ++i) {
final Edge edge = triangle.getEdge(i);
if (borderEdges.remove(edge)) {
continue;
}
borderEdges.add(edge);
}
}
// Add triangles between the remembered edges and the new vertex.
for (Edge edge : borderEdges) {
triangles.add(edge.createTriangle(vertexD));
}
if (!vertexBacklog.isEmpty()) {
// Remove the new vertex
vertices.remove(vertex);
// Clone, clear and work through the backlog
final List<BlockVector3> vertexBacklog2 = new ArrayList<>(vertexBacklog);
vertexBacklog.clear();
for (BlockVector3 vertex2 : vertexBacklog2) {
addVertex(vertex2);
}
// Re-add the new vertex after the backlog.
vertices.add(vertex);
}
return true;
}
public boolean isDefined() {
return !triangles.isEmpty();
}
@Override
public BlockVector3 getMinimumPoint() {
return minimumPoint;
}
@Override
public BlockVector3 getMaximumPoint() {
return maximumPoint;
}
@Override
public Vector3 getCenter() {
return centerAccum.toVector3().divide(vertices.size());
}
@Override
public void expand(BlockVector3... changes) throws RegionOperationException {
}
@Override
public void contract(BlockVector3... changes) throws RegionOperationException {
}
@Override
public void shift(BlockVector3 change) throws RegionOperationException {
Vector3 vec = change.toVector3();
shiftCollection(vertices, change);
shiftCollection(vertexBacklog, change);
for (int i = 0; i < triangles.size(); ++i) {
final Triangle triangle = triangles.get(i);
final Vector3 v0 = vec.add(triangle.getVertex(0));
final Vector3 v1 = vec.add(triangle.getVertex(1));
final Vector3 v2 = vec.add(triangle.getVertex(2));
triangles.set(i, new Triangle(v0, v1, v2));
}
minimumPoint = change.add(minimumPoint);
maximumPoint = change.add(maximumPoint);
centerAccum = change.multiply(vertices.size()).add(centerAccum);
lastTriangle = null;
}
private static void shiftCollection(Collection<BlockVector3> collection, BlockVector3 change) {
final List<BlockVector3> tmp = new ArrayList<>(collection);
collection.clear();
for (BlockVector3 vertex : tmp) {
collection.add(change.add(vertex));
}
}
@Override
public boolean contains(BlockVector3 position) {
if (!isDefined()) {
return false;
}
final BlockVector3 min = getMinimumPoint();
final BlockVector3 max = getMaximumPoint();
if (!position.containedWithin(min, max)) {
return false;
}
return containsRaw(position.toVector3());
}
private boolean containsRaw(Vector3 pt) {
if (lastTriangle != null && lastTriangle.above(pt)) {
return false;
}
for (Triangle triangle : triangles) {
if (lastTriangle == triangle) {
continue;
}
if (triangle.above(pt)) {
lastTriangle = triangle;
return false;
}
}
return true;
}
public Collection<BlockVector3> getVertices() {
if (vertexBacklog.isEmpty()) {
return vertices;
}
final List<BlockVector3> ret = new ArrayList<>(vertices);
ret.addAll(vertexBacklog);
return ret;
}
public Collection<Triangle> getTriangles() {
return triangles;
}
@Override
public AbstractRegion clone() {
return new ConvexPolyhedralRegion(this);
}
@Override
public boolean containsEntireCuboid(int bx, int tx, int by, int ty, int bz, int tz) {
return false;
}
}

View File

@ -1,430 +1,430 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.regions;
import com.boydti.fawe.beta.Filter;
import com.boydti.fawe.beta.IChunk;
import com.boydti.fawe.beta.IChunkGet;
import com.boydti.fawe.beta.IChunkSet;
import com.boydti.fawe.beta.implementation.filter.block.ChunkFilterBlock;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.math.Vector2;
import com.sk89q.worldedit.math.Vector3;
import com.sk89q.worldedit.math.geom.Polygons;
import com.sk89q.worldedit.regions.iterator.FlatRegion3DIterator;
import com.sk89q.worldedit.regions.iterator.FlatRegionIterator;
import com.sk89q.worldedit.util.formatting.text.TranslatableComponent;
import com.sk89q.worldedit.world.World;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Iterator;
import java.util.List;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Represents a cylindrical region.
*/
public class CylinderRegion extends AbstractRegion implements FlatRegion {
private BlockVector2 center;
private Vector2 radius;
private Vector2 radiusInverse;
private int minY;
private int maxY;
private boolean hasY = false;
/**
* Construct the region.
*/
public CylinderRegion() {
this((World) null);
}
/**
* Construct the region.
*
* @param world the world
*/
public CylinderRegion(World world) {
this(world, BlockVector3.ZERO, Vector2.ZERO, 0, 0);
hasY = false;
}
/**
* Construct the region.
*
* @param world the world
* @param center the center position
* @param radius the radius along the X and Z axes
* @param minY the minimum Y, inclusive
* @param maxY the maximum Y, inclusive
*/
public CylinderRegion(World world, BlockVector3 center, Vector2 radius, int minY, int maxY) {
super(world);
setCenter(center.toBlockVector2());
setRadius(radius);
this.minY = minY;
this.maxY = maxY;
hasY = true;
}
/**
* Construct the region.
*
* @param center the center position
* @param radius the radius along the X and Z axes
* @param minY the minimum Y, inclusive
* @param maxY the maximum Y, inclusive
*/
public CylinderRegion(BlockVector3 center, Vector2 radius, int minY, int maxY) {
super(null);
setCenter(center.toBlockVector2());
setRadius(radius);
this.minY = minY;
this.maxY = maxY;
hasY = true;
}
public CylinderRegion(CylinderRegion region) {
this(region.world, region.getCenter().toBlockPoint(), region.getRadius(), region.minY, region.maxY);
hasY = region.hasY;
}
@Override
public Vector3 getCenter() {
return center.toVector3((maxY + minY) / 2);
}
/**
* Sets the main center point of the region.
*
* @param center the center point
*/
public void setCenter(BlockVector2 center) {
this.center = center;
}
/**
* Returns the radius of the cylinder.
*
* @return the radius along the X and Z axes
*/
public Vector2 getRadius() {
return radius.subtract(0.5, 0.5);
}
/**
* Sets the radius of the cylinder.
*
* @param radius the radius along the X and Z axes
*/
public void setRadius(Vector2 radius) {
this.radius = radius.add(0.5, 0.5);
this.radiusInverse = Vector2.ONE.divide(radius);
}
/**
* Extends the radius to be at least the given radius.
*
* @param minRadius the minimum radius
*/
public void extendRadius(Vector2 minRadius) {
setRadius(minRadius.getMaximum(getRadius()));
}
/**
* Set the minimum Y.
*
* @param y the y
*/
public void setMinimumY(int y) {
hasY = true;
minY = y;
}
/**
* Se the maximum Y.
*
* @param y the y
*/
public void setMaximumY(int y) {
hasY = true;
maxY = y;
}
@Override
public BlockVector3 getMinimumPoint() {
return center.toVector2().subtract(getRadius()).toVector3(minY).toBlockPoint();
}
@Override
public BlockVector3 getMaximumPoint() {
return center.toVector2().add(getRadius()).toVector3(maxY).toBlockPoint();
}
@Override
public int getMaximumY() {
int worldMax = world != null ? world.getMaxY() - 1 : 255;
if (maxY > worldMax) {
return maxY = worldMax;
}
return maxY;
}
@Override
public int getMinimumY() {
if (minY < 0) {
return minY = 0;
}
return minY;
}
private static final BigDecimal PI = BigDecimal.valueOf(Math.PI);
@Override
public long getVolume() {
return BigDecimal.valueOf(radius.getX())
.multiply(BigDecimal.valueOf(radius.getZ()))
.multiply(PI)
.multiply(BigDecimal.valueOf(getHeight()))
.setScale(0, RoundingMode.FLOOR)
.longValue();
}
@Override
public int getWidth() {
return (int) (2 * radius.getX());
}
@Override
public int getHeight() {
return maxY - minY + 1;
}
@Override
public int getLength() {
return (int) (2 * radius.getZ());
}
private BlockVector2 calculateDiff2D(BlockVector3... changes) throws RegionOperationException {
BlockVector2 diff = BlockVector2.ZERO;
for (BlockVector3 change : changes) {
diff = diff.add(change.toBlockVector2());
}
if ((diff.getBlockX() & 1) + (diff.getBlockZ() & 1) != 0) {
throw new RegionOperationException(TranslatableComponent.of("worldedit.selection.cylinder.error.even-horizontal"));
}
return diff.divide(2).floor();
}
private BlockVector2 calculateChanges2D(BlockVector3... changes) {
BlockVector2 total = BlockVector2.ZERO;
for (BlockVector3 change : changes) {
total = total.add(change.toBlockVector2().abs());
}
return total.divide(2).floor();
}
/**
* Expand the region.
* Expand the region.
*
* @param changes array/arguments with multiple related changes
*/
@Override
public void expand(BlockVector3... changes) throws RegionOperationException {
center = center.add(calculateDiff2D(changes));
radius = radius.add(calculateChanges2D(changes).toVector2());
this.radiusInverse = Vector2.ONE.divide(radius);
for (BlockVector3 change : changes) {
int changeY = change.getBlockY();
if (changeY > 0) {
maxY += changeY;
} else {
minY += changeY;
}
}
}
/**
* Contract the region.
*
* @param changes array/arguments with multiple related changes
* @throws RegionOperationException
*/
@Override
public void contract(BlockVector3... changes) throws RegionOperationException {
center = center.subtract(calculateDiff2D(changes));
Vector2 newRadius = radius.subtract(calculateChanges2D(changes).toVector2());
radius = Vector2.at(1.5, 1.5).getMaximum(newRadius);
this.radiusInverse = Vector2.ONE.divide(radius);
for (BlockVector3 change : changes) {
int height = maxY - minY;
int changeY = change.getBlockY();
if (changeY > 0) {
minY += Math.min(height, changeY);
} else {
maxY += Math.max(-height, changeY);
}
}
}
@Override
public void shift(BlockVector3 change) throws RegionOperationException {
center = center.add(change.toBlockVector2());
int changeY = change.getBlockY();
maxY += changeY;
minY += changeY;
}
/**
* Checks to see if a point is inside this region.
*/
/* Slow and unnecessary
@Override
public boolean contains(BlockVector3 position) {
final int blockY = position.getBlockY();
if (blockY < minY || blockY > maxY) {
return false;
}
return position.toBlockVector2().subtract(center).toVector2().divide(radius).lengthSq() <= 1;
}
*/
/**
* Checks to see if a point is inside this region.
*/
@Override
public boolean contains(int x, int y, int z) {
if (y < minY || y > maxY) {
return false;
}
return contains(x, z);
}
@Override
public boolean contains(int x, int z) {
double dx = Math.abs(x - center.getBlockX()) * radiusInverse.getX();
double dz = Math.abs(z - center.getBlockZ()) * radiusInverse.getZ();
return dx * dx + dz * dz <= 1;
}
@Override
public boolean contains(BlockVector3 position) {
return contains(position.getX(), position.getY(), position.getZ());
}
/**
* Sets the height of the cylinder to fit the specified Y.
*
* @param y the y value
* @return true if the area was expanded
*/
public boolean setY(int y) {
if (!hasY) {
minY = y;
maxY = y;
hasY = true;
return true;
} else if (y < minY) {
minY = y;
return true;
} else if (y > maxY) {
maxY = y;
return true;
}
return false;
}
@Override
public Iterator<BlockVector3> iterator() {
return new FlatRegion3DIterator(this);
}
@Override
public Iterable<BlockVector2> asFlatRegion() {
return () -> new FlatRegionIterator(CylinderRegion.this);
}
/**
* Returns string representation in the format.
* "(centerX, centerZ) - (radiusX, radiusZ) - (minY, maxY)"
*
* @return string
*/
@Override
public String toString() {
return center + " - " + radius + "(" + minY + ", " + maxY + ")";
}
@Override
public CylinderRegion clone() {
return (CylinderRegion) super.clone();
}
@Override
public List<BlockVector2> polygonize(int maxPoints) {
return Polygons.polygonizeCylinder(center, radius, maxPoints);
}
/**
* Return a new instance with the given center and radius in the X and Z
* axes with a Y that extends from the bottom of the extent to the top
* of the extent.
*
* @param extent the extent
* @param center the center position
* @param radius the radius in the X and Z axes
* @return a region
*/
public static CylinderRegion createRadius(Extent extent, BlockVector3 center, double radius) {
checkNotNull(extent);
checkNotNull(center);
Vector2 radiusVec = Vector2.at(radius, radius);
int minY = extent.getMinimumPoint().getBlockY();
int maxY = extent.getMaximumPoint().getBlockY();
return new CylinderRegion(center, radiusVec, minY, maxY);
}
@Override
public void filter(final IChunk chunk, final Filter filter, final ChunkFilterBlock block,
final IChunkGet get, final IChunkSet set, boolean full) {
int bcx = chunk.getX() >> 4;
int bcz = chunk.getZ() >> 4;
int tcx = bcx + 15;
int tcz = bcz + 15;
if (contains(bcx, bcz) && contains(tcx, tcz)) {
filter(chunk, filter, block, get, set, minY, maxY, full);
return;
}
super.filter(chunk, filter, block, get, set, full);
}
}
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.regions;
import com.boydti.fawe.beta.Filter;
import com.boydti.fawe.beta.IChunk;
import com.boydti.fawe.beta.IChunkGet;
import com.boydti.fawe.beta.IChunkSet;
import com.boydti.fawe.beta.implementation.filter.block.ChunkFilterBlock;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.math.Vector2;
import com.sk89q.worldedit.math.Vector3;
import com.sk89q.worldedit.math.geom.Polygons;
import com.sk89q.worldedit.regions.iterator.FlatRegion3DIterator;
import com.sk89q.worldedit.regions.iterator.FlatRegionIterator;
import com.sk89q.worldedit.util.formatting.text.TranslatableComponent;
import com.sk89q.worldedit.world.World;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Iterator;
import java.util.List;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Represents a cylindrical region.
*/
public class CylinderRegion extends AbstractRegion implements FlatRegion {
private BlockVector2 center;
private Vector2 radius;
private Vector2 radiusInverse;
private int minY;
private int maxY;
private boolean hasY = false;
/**
* Construct the region.
*/
public CylinderRegion() {
this((World) null);
}
/**
* Construct the region.
*
* @param world the world
*/
public CylinderRegion(World world) {
this(world, BlockVector3.ZERO, Vector2.ZERO, 0, 0);
hasY = false;
}
/**
* Construct the region.
*
* @param world the world
* @param center the center position
* @param radius the radius along the X and Z axes
* @param minY the minimum Y, inclusive
* @param maxY the maximum Y, inclusive
*/
public CylinderRegion(World world, BlockVector3 center, Vector2 radius, int minY, int maxY) {
super(world);
setCenter(center.toBlockVector2());
setRadius(radius);
this.minY = minY;
this.maxY = maxY;
hasY = true;
}
/**
* Construct the region.
*
* @param center the center position
* @param radius the radius along the X and Z axes
* @param minY the minimum Y, inclusive
* @param maxY the maximum Y, inclusive
*/
public CylinderRegion(BlockVector3 center, Vector2 radius, int minY, int maxY) {
super(null);
setCenter(center.toBlockVector2());
setRadius(radius);
this.minY = minY;
this.maxY = maxY;
hasY = true;
}
public CylinderRegion(CylinderRegion region) {
this(region.world, region.getCenter().toBlockPoint(), region.getRadius(), region.minY, region.maxY);
hasY = region.hasY;
}
@Override
public Vector3 getCenter() {
return center.toVector3((maxY + minY) / 2);
}
/**
* Sets the main center point of the region.
*
* @param center the center point
*/
public void setCenter(BlockVector2 center) {
this.center = center;
}
/**
* Returns the radius of the cylinder.
*
* @return the radius along the X and Z axes
*/
public Vector2 getRadius() {
return radius.subtract(0.5, 0.5);
}
/**
* Sets the radius of the cylinder.
*
* @param radius the radius along the X and Z axes
*/
public void setRadius(Vector2 radius) {
this.radius = radius.add(0.5, 0.5);
this.radiusInverse = Vector2.ONE.divide(radius);
}
/**
* Extends the radius to be at least the given radius.
*
* @param minRadius the minimum radius
*/
public void extendRadius(Vector2 minRadius) {
setRadius(minRadius.getMaximum(getRadius()));
}
/**
* Set the minimum Y.
*
* @param y the y
*/
public void setMinimumY(int y) {
hasY = true;
minY = y;
}
/**
* Se the maximum Y.
*
* @param y the y
*/
public void setMaximumY(int y) {
hasY = true;
maxY = y;
}
@Override
public BlockVector3 getMinimumPoint() {
return center.toVector2().subtract(getRadius()).toVector3(minY).toBlockPoint();
}
@Override
public BlockVector3 getMaximumPoint() {
return center.toVector2().add(getRadius()).toVector3(maxY).toBlockPoint();
}
@Override
public int getMaximumY() {
int worldMax = world != null ? world.getMaxY() - 1 : 255;
if (maxY > worldMax) {
return maxY = worldMax;
}
return maxY;
}
@Override
public int getMinimumY() {
if (minY < 0) {
return minY = 0;
}
return minY;
}
private static final BigDecimal PI = BigDecimal.valueOf(Math.PI);
@Override
public long getVolume() {
return BigDecimal.valueOf(radius.getX())
.multiply(BigDecimal.valueOf(radius.getZ()))
.multiply(PI)
.multiply(BigDecimal.valueOf(getHeight()))
.setScale(0, RoundingMode.FLOOR)
.longValue();
}
@Override
public int getWidth() {
return (int) (2 * radius.getX());
}
@Override
public int getHeight() {
return maxY - minY + 1;
}
@Override
public int getLength() {
return (int) (2 * radius.getZ());
}
private BlockVector2 calculateDiff2D(BlockVector3... changes) throws RegionOperationException {
BlockVector2 diff = BlockVector2.ZERO;
for (BlockVector3 change : changes) {
diff = diff.add(change.toBlockVector2());
}
if ((diff.getBlockX() & 1) + (diff.getBlockZ() & 1) != 0) {
throw new RegionOperationException(TranslatableComponent.of("worldedit.selection.cylinder.error.even-horizontal"));
}
return diff.divide(2).floor();
}
private BlockVector2 calculateChanges2D(BlockVector3... changes) {
BlockVector2 total = BlockVector2.ZERO;
for (BlockVector3 change : changes) {
total = total.add(change.toBlockVector2().abs());
}
return total.divide(2).floor();
}
/**
* Expand the region.
* Expand the region.
*
* @param changes array/arguments with multiple related changes
*/
@Override
public void expand(BlockVector3... changes) throws RegionOperationException {
center = center.add(calculateDiff2D(changes));
radius = radius.add(calculateChanges2D(changes).toVector2());
this.radiusInverse = Vector2.ONE.divide(radius);
for (BlockVector3 change : changes) {
int changeY = change.getBlockY();
if (changeY > 0) {
maxY += changeY;
} else {
minY += changeY;
}
}
}
/**
* Contract the region.
*
* @param changes array/arguments with multiple related changes
* @throws RegionOperationException
*/
@Override
public void contract(BlockVector3... changes) throws RegionOperationException {
center = center.subtract(calculateDiff2D(changes));
Vector2 newRadius = radius.subtract(calculateChanges2D(changes).toVector2());
radius = Vector2.at(1.5, 1.5).getMaximum(newRadius);
this.radiusInverse = Vector2.ONE.divide(radius);
for (BlockVector3 change : changes) {
int height = maxY - minY;
int changeY = change.getBlockY();
if (changeY > 0) {
minY += Math.min(height, changeY);
} else {
maxY += Math.max(-height, changeY);
}
}
}
@Override
public void shift(BlockVector3 change) throws RegionOperationException {
center = center.add(change.toBlockVector2());
int changeY = change.getBlockY();
maxY += changeY;
minY += changeY;
}
/**
* Checks to see if a point is inside this region.
*/
/* Slow and unnecessary
@Override
public boolean contains(BlockVector3 position) {
final int blockY = position.getBlockY();
if (blockY < minY || blockY > maxY) {
return false;
}
return position.toBlockVector2().subtract(center).toVector2().divide(radius).lengthSq() <= 1;
}
*/
/**
* Checks to see if a point is inside this region.
*/
@Override
public boolean contains(int x, int y, int z) {
if (y < minY || y > maxY) {
return false;
}
return contains(x, z);
}
@Override
public boolean contains(int x, int z) {
double dx = Math.abs(x - center.getBlockX()) * radiusInverse.getX();
double dz = Math.abs(z - center.getBlockZ()) * radiusInverse.getZ();
return dx * dx + dz * dz <= 1;
}
@Override
public boolean contains(BlockVector3 position) {
return contains(position.getX(), position.getY(), position.getZ());
}
/**
* Sets the height of the cylinder to fit the specified Y.
*
* @param y the y value
* @return true if the area was expanded
*/
public boolean setY(int y) {
if (!hasY) {
minY = y;
maxY = y;
hasY = true;
return true;
} else if (y < minY) {
minY = y;
return true;
} else if (y > maxY) {
maxY = y;
return true;
}
return false;
}
@Override
public Iterator<BlockVector3> iterator() {
return new FlatRegion3DIterator(this);
}
@Override
public Iterable<BlockVector2> asFlatRegion() {
return () -> new FlatRegionIterator(CylinderRegion.this);
}
/**
* Returns string representation in the format.
* "(centerX, centerZ) - (radiusX, radiusZ) - (minY, maxY)"
*
* @return string
*/
@Override
public String toString() {
return center + " - " + radius + "(" + minY + ", " + maxY + ")";
}
@Override
public CylinderRegion clone() {
return (CylinderRegion) super.clone();
}
@Override
public List<BlockVector2> polygonize(int maxPoints) {
return Polygons.polygonizeCylinder(center, radius, maxPoints);
}
/**
* Return a new instance with the given center and radius in the X and Z
* axes with a Y that extends from the bottom of the extent to the top
* of the extent.
*
* @param extent the extent
* @param center the center position
* @param radius the radius in the X and Z axes
* @return a region
*/
public static CylinderRegion createRadius(Extent extent, BlockVector3 center, double radius) {
checkNotNull(extent);
checkNotNull(center);
Vector2 radiusVec = Vector2.at(radius, radius);
int minY = extent.getMinimumPoint().getBlockY();
int maxY = extent.getMaximumPoint().getBlockY();
return new CylinderRegion(center, radiusVec, minY, maxY);
}
@Override
public void filter(final IChunk chunk, final Filter filter, final ChunkFilterBlock block,
final IChunkGet get, final IChunkSet set, boolean full) {
int bcx = chunk.getX() >> 4;
int bcz = chunk.getZ() >> 4;
int tcx = bcx + 15;
int tcz = bcz + 15;
if (contains(bcx, bcz) && contains(tcx, tcz)) {
filter(chunk, filter, block, get, set, minY, maxY, full);
return;
}
super.filter(chunk, filter, block, get, set, full);
}
}

View File

@ -1,36 +1,36 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.regions;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.util.formatting.text.Component;
public class RegionOperationException extends WorldEditException {
@Deprecated
public RegionOperationException(String msg) {
super(msg);
}
public RegionOperationException(Component msg) {
super(msg);
}
}
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.regions;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.util.formatting.text.Component;
public class RegionOperationException extends WorldEditException {
@Deprecated
public RegionOperationException(String msg) {
super(msg);
}
public RegionOperationException(Component msg) {
super(msg);
}
}

View File

@ -1,90 +1,90 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.regions.polyhedron;
import com.sk89q.worldedit.math.Vector3;
import static com.google.common.base.Preconditions.checkNotNull;
public class Edge {
private final Vector3 start;
private final Vector3 end;
public Edge(Vector3 start, Vector3 end) {
checkNotNull(start);
checkNotNull(end);
this.start = start;
this.end = end;
}
@Override
public boolean equals(Object other) {
if (!(other instanceof Edge)) {
return false;
}
Edge otherEdge = (Edge) other;
if ((this.start == otherEdge.end) && (this.end == otherEdge.start)) {
return true;
}
if ((this.end == otherEdge.end) && (this.start == otherEdge.start)) {
return true;
}
return false;
}
@Override
public int hashCode() {
return start.hashCode() ^ end.hashCode();
}
@Override
public String toString() {
return "(" + this.start + "," + this.end + ")";
}
/**
* Create a triangle from { this.start, this.end, vertex }
*
* @param vertex the 3rd vertex for the triangle
* @return a triangle
*/
public Triangle createTriangle(Vector3 vertex) {
checkNotNull(vertex);
return new Triangle(this.start, this.end, vertex);
}
/**
* Create a triangle from { this.start, vertex, this.end }.
*
* @param vertex the second vertex
* @return a new triangle
*/
public Triangle createTriangle2(Vector3 vertex) {
checkNotNull(vertex);
return new Triangle(this.start, vertex, this.end);
}
}
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.regions.polyhedron;
import com.sk89q.worldedit.math.Vector3;
import static com.google.common.base.Preconditions.checkNotNull;
public class Edge {
private final Vector3 start;
private final Vector3 end;
public Edge(Vector3 start, Vector3 end) {
checkNotNull(start);
checkNotNull(end);
this.start = start;
this.end = end;
}
@Override
public boolean equals(Object other) {
if (!(other instanceof Edge)) {
return false;
}
Edge otherEdge = (Edge) other;
if ((this.start == otherEdge.end) && (this.end == otherEdge.start)) {
return true;
}
if ((this.end == otherEdge.end) && (this.start == otherEdge.start)) {
return true;
}
return false;
}
@Override
public int hashCode() {
return start.hashCode() ^ end.hashCode();
}
@Override
public String toString() {
return "(" + this.start + "," + this.end + ")";
}
/**
* Create a triangle from { this.start, this.end, vertex }
*
* @param vertex the 3rd vertex for the triangle
* @return a triangle
*/
public Triangle createTriangle(Vector3 vertex) {
checkNotNull(vertex);
return new Triangle(this.start, this.end, vertex);
}
/**
* Create a triangle from { this.start, vertex, this.end }.
*
* @param vertex the second vertex
* @return a new triangle
*/
public Triangle createTriangle2(Vector3 vertex) {
checkNotNull(vertex);
return new Triangle(this.start, vertex, this.end);
}
}

View File

@ -1,113 +1,113 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.regions.polyhedron;
import com.sk89q.worldedit.math.Vector3;
import static com.google.common.base.Preconditions.checkNotNull;
public class Triangle {
private String tag = "Triangle";
private final Vector3[] vertices;
private final Vector3 normal;
private final double maxDotProduct;
/**
* Constructs a triangle with the given vertices (counter-clockwise).
*
* @param v0 first vertex
* @param v1 second vertex
* @param v2 third vertex
*/
public Triangle(Vector3 v0, Vector3 v1, Vector3 v2) {
checkNotNull(v0);
checkNotNull(v1);
checkNotNull(v2);
vertices = new Vector3[] { v0, v1, v2 };
this.normal = v1.subtract(v0).cross(v2.subtract(v0)).normalize();
this.maxDotProduct = Math.max(Math.max(normal.dot(v0), normal.dot(v1)), normal.dot(v2));
}
/**
* Returns the triangle's vertex with the given index, counter-clockwise.
*
* @param index Vertex index. Valid input: 0..2
* @return a vertex
*/
public Vector3 getVertex(int index) {
return vertices[index];
}
/**
* Returns the triangle's edge with the given index, counter-clockwise.
*
* @param index Edge index. Valid input: 0..2
* @return an edge
*/
public Edge getEdge(int index) {
if (index == vertices.length - 1) {
return new Edge(vertices[index], vertices[0]);
}
return new Edge(vertices[index], vertices[index + 1]);
}
/**
* Returns whether the given point is above the plane the triangle is in.
*
* @param pt the point to test
* @return true if the point is below
*/
public boolean below(Vector3 pt) {
checkNotNull(pt);
return normal.dot(pt) < maxDotProduct;
}
/**
* Returns whether the given point is above the plane the triangle is in.
*
* @param pt the point to test
* @return true if the point is above
*/
public boolean above(Vector3 pt) {
checkNotNull(pt);
return normal.dot(pt) > maxDotProduct;
}
/**
* Set the triangle's tag.
*
* @param tag the tag
* @return this object
*/
public Triangle tag(String tag) {
checkNotNull(tag);
this.tag = tag;
return this;
}
@Override
public String toString() {
return tag + "(" + this.vertices[0] + "," + this.vertices[1] + "," + this.vertices[2] + ")";
}
}
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.regions.polyhedron;
import com.sk89q.worldedit.math.Vector3;
import static com.google.common.base.Preconditions.checkNotNull;
public class Triangle {
private String tag = "Triangle";
private final Vector3[] vertices;
private final Vector3 normal;
private final double maxDotProduct;
/**
* Constructs a triangle with the given vertices (counter-clockwise).
*
* @param v0 first vertex
* @param v1 second vertex
* @param v2 third vertex
*/
public Triangle(Vector3 v0, Vector3 v1, Vector3 v2) {
checkNotNull(v0);
checkNotNull(v1);
checkNotNull(v2);
vertices = new Vector3[] { v0, v1, v2 };
this.normal = v1.subtract(v0).cross(v2.subtract(v0)).normalize();
this.maxDotProduct = Math.max(Math.max(normal.dot(v0), normal.dot(v1)), normal.dot(v2));
}
/**
* Returns the triangle's vertex with the given index, counter-clockwise.
*
* @param index Vertex index. Valid input: 0..2
* @return a vertex
*/
public Vector3 getVertex(int index) {
return vertices[index];
}
/**
* Returns the triangle's edge with the given index, counter-clockwise.
*
* @param index Edge index. Valid input: 0..2
* @return an edge
*/
public Edge getEdge(int index) {
if (index == vertices.length - 1) {
return new Edge(vertices[index], vertices[0]);
}
return new Edge(vertices[index], vertices[index + 1]);
}
/**
* Returns whether the given point is above the plane the triangle is in.
*
* @param pt the point to test
* @return true if the point is below
*/
public boolean below(Vector3 pt) {
checkNotNull(pt);
return normal.dot(pt) < maxDotProduct;
}
/**
* Returns whether the given point is above the plane the triangle is in.
*
* @param pt the point to test
* @return true if the point is above
*/
public boolean above(Vector3 pt) {
checkNotNull(pt);
return normal.dot(pt) > maxDotProduct;
}
/**
* Set the triangle's tag.
*
* @param tag the tag
* @return this object
*/
public Triangle tag(String tag) {
checkNotNull(tag);
this.tag = tag;
return this;
}
@Override
public String toString() {
return tag + "(" + this.vertices[0] + "," + this.vertices[1] + "," + this.vertices[2] + ")";
}
}