diff --git a/src/main/java/com/sk89q/worldedit/math/transform/AffineTransform.java b/src/main/java/com/sk89q/worldedit/math/transform/AffineTransform.java new file mode 100644 index 000000000..4fef9b606 --- /dev/null +++ b/src/main/java/com/sk89q/worldedit/math/transform/AffineTransform.java @@ -0,0 +1,298 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * 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 . + */ + +package com.sk89q.worldedit.math.transform; + +import com.sk89q.worldedit.Vector; + +/** + * An affine transform. + *

+ * This class is from the that, then this affine transform. + * + * @param that the transform to apply first + * @return the composition this * that + */ + public AffineTransform concatenate(AffineTransform that) { + double n00 = m00 * that.m00 + m01 * that.m10 + m02 * that.m20; + double n01 = m00 * that.m01 + m01 * that.m11 + m02 * that.m21; + double n02 = m00 * that.m02 + m01 * that.m12 + m02 * that.m22; + double n03 = m00 * that.m03 + m01 * that.m13 + m02 * that.m23 + m03; + double n10 = m10 * that.m00 + m11 * that.m10 + m12 * that.m20; + double n11 = m10 * that.m01 + m11 * that.m11 + m12 * that.m21; + double n12 = m10 * that.m02 + m11 * that.m12 + m12 * that.m22; + double n13 = m10 * that.m03 + m11 * that.m13 + m12 * that.m23 + m13; + double n20 = m20 * that.m00 + m21 * that.m10 + m22 * that.m20; + double n21 = m20 * that.m01 + m21 * that.m11 + m22 * that.m21; + double n22 = m20 * that.m02 + m21 * that.m12 + m22 * that.m22; + double n23 = m20 * that.m03 + m21 * that.m13 + m22 * that.m23 + m23; + return new AffineTransform( + n00, n01, n02, n03, + n10, n11, n12, n13, + n20, n21, n22, n23); + } + + /** + * Return the affine transform created by applying first this affine + * transform, then the affine transform given by that. + * + * @param that the transform to apply in a second step + * @return the composition that * this + */ + public AffineTransform preConcatenate(AffineTransform that) { + double n00 = that.m00 * m00 + that.m01 * m10 + that.m02 * m20; + double n01 = that.m00 * m01 + that.m01 * m11 + that.m02 * m21; + double n02 = that.m00 * m02 + that.m01 * m12 + that.m02 * m22; + double n03 = that.m00 * m03 + that.m01 * m13 + that.m02 * m23 + that.m03; + double n10 = that.m10 * m00 + that.m11 * m10 + that.m12 * m20; + double n11 = that.m10 * m01 + that.m11 * m11 + that.m12 * m21; + double n12 = that.m10 * m02 + that.m11 * m12 + that.m12 * m22; + double n13 = that.m10 * m03 + that.m11 * m13 + that.m12 * m23 + that.m13; + double n20 = that.m20 * m00 + that.m21 * m10 + that.m22 * m20; + double n21 = that.m20 * m01 + that.m21 * m11 + that.m22 * m21; + double n22 = that.m20 * m02 + that.m21 * m12 + that.m22 * m22; + double n23 = that.m20 * m03 + that.m21 * m13 + that.m22 * m23 + that.m23; + return new AffineTransform( + n00, n01, n02, n03, + n10, n11, n12, n13, + n20, n21, n22, n23); + } + + public AffineTransform translate(Vector vec) { + return translate(vec.getX(), vec.getY(), vec.getZ()); + } + + public AffineTransform translate(double x, double y, double z) { + return concatenate(new AffineTransform(1, 0, 0, x, 0, 1, 0, y, 0, 0, 1, z)); + } + + public AffineTransform rotateX(double theta) { + double cot = Math.cos(theta); + double sit = Math.sin(theta); + return concatenate( + new AffineTransform( + 1, 0, 0, 0, + 0, cot, -sit, 0, + 0, sit, cot, 0)); + } + + public AffineTransform rotateY(double theta) { + double cot = Math.cos(theta); + double sit = Math.sin(theta); + return concatenate( + new AffineTransform( + cot, 0, sit, 0, + 0, 1, 0, 0, + -sit, 0, cot, 0)); + } + + public AffineTransform rotateZ(double theta) { + double cot = Math.cos(theta); + double sit = Math.sin(theta); + return concatenate( + new AffineTransform( + cot, -sit, 0, 0, + sit, cot, 0, 0, + 0, 0, 1, 0)); + } + + public AffineTransform scale(double s) { + return scale(s, s, s); + } + + public AffineTransform scale(double sx, double sy, double sz) { + return concatenate(new AffineTransform(sx, 0, 0, 0, 0, sy, 0, 0, 0, 0, sz, 0)); + } + + @Override + public Vector apply(Vector vector) { + return new Vector( + vector.getX() * m00 + vector.getY() * m01 + vector.getZ() * m02 + m03, + vector.getX() * m10 + vector.getY() * m11 + vector.getZ() * m12 + m13, + vector.getX() * m20 + vector.getY() * m21 + vector.getZ() * m22 + m23); + } + + @Override + public Transform combine(Transform other) { + if (other instanceof AffineTransform) { + return concatenate((AffineTransform) other); + } else { + return new CombinedTransform(this, other); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/sk89q/worldedit/math/transform/CombinedTransform.java b/src/main/java/com/sk89q/worldedit/math/transform/CombinedTransform.java new file mode 100644 index 000000000..893e3c384 --- /dev/null +++ b/src/main/java/com/sk89q/worldedit/math/transform/CombinedTransform.java @@ -0,0 +1,77 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * 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 . + */ + +package com.sk89q.worldedit.math.transform; + +import com.sk89q.worldedit.Vector; + +import java.util.Arrays; +import java.util.Collection; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * Combines several transforms in order. + */ +public class CombinedTransform implements Transform { + + private final Transform[] transforms; + + /** + * Create a new combined transformation. + * + * @param transforms a list of transformations + */ + public CombinedTransform(Transform... transforms) { + checkNotNull(transforms); + this.transforms = Arrays.copyOf(transforms, transforms.length); + } + + /** + * Create a new combined transformation. + * + * @param transforms a list of transformations + */ + public CombinedTransform(Collection transforms) { + this(transforms.toArray(new Transform[checkNotNull(transforms).size()])); + } + + @Override + public Vector apply(Vector vector) { + for (Transform transform : transforms) { + vector = transform.apply(vector); + } + return vector; + } + + @Override + public Transform combine(Transform other) { + checkNotNull(other); + if (other instanceof CombinedTransform) { + CombinedTransform combinedOther = (CombinedTransform) other; + Transform[] newTransforms = new Transform[transforms.length + combinedOther.transforms.length]; + System.arraycopy(transforms, 0, newTransforms, 0, transforms.length); + System.arraycopy(combinedOther.transforms, 0, newTransforms, transforms.length, combinedOther.transforms.length); + return new CombinedTransform(newTransforms); + } else { + return new CombinedTransform(this, other); + } + } + +} diff --git a/src/main/java/com/sk89q/worldedit/math/transform/Identity.java b/src/main/java/com/sk89q/worldedit/math/transform/Identity.java new file mode 100644 index 000000000..e13547de1 --- /dev/null +++ b/src/main/java/com/sk89q/worldedit/math/transform/Identity.java @@ -0,0 +1,42 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * 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 . + */ + +package com.sk89q.worldedit.math.transform; + +import com.sk89q.worldedit.Vector; + +/** + * Makes no transformation to given vectors. + */ +public class Identity implements Transform { + + @Override + public Vector apply(Vector vector) { + return vector; + } + + @Override + public Transform combine(Transform other) { + if (other instanceof Identity) { + return this; + } else { + return new CombinedTransform(this, other); + } + } +} diff --git a/src/main/java/com/sk89q/worldedit/math/transform/Transform.java b/src/main/java/com/sk89q/worldedit/math/transform/Transform.java new file mode 100644 index 000000000..38aba52e9 --- /dev/null +++ b/src/main/java/com/sk89q/worldedit/math/transform/Transform.java @@ -0,0 +1,38 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * 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 . + */ + +package com.sk89q.worldedit.math.transform; + +import com.google.common.base.Function; +import com.sk89q.worldedit.Vector; + +/** + * Makes a transformation of {@link Vector}s. + */ +public interface Transform extends Function { + + /** + * Create a new {@link Transform} that combines this transform with another. + * + * @param other the other transform to occur second + * @return a new transform + */ + Transform combine(Transform other); + +}