001/*
002 * This file is part of Baritone.
003 *
004 * Baritone is free software: you can redistribute it and/or modify
005 * it under the terms of the GNU Lesser General Public License as published by
006 * the Free Software Foundation, either version 3 of the License, or
007 * (at your option) any later version.
008 *
009 * Baritone is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
012 * GNU Lesser General Public License for more details.
013 *
014 * You should have received a copy of the GNU Lesser General Public License
015 * along with Baritone.  If not, see <https://www.gnu.org/licenses/>.
016 */
017
018package baritone.api.schematic.mask.shape;
019
020import baritone.api.schematic.mask.AbstractMask;
021import baritone.api.schematic.mask.StaticMask;
022import net.minecraft.core.Direction;
023
024/**
025 * @author Brady
026 */
027public final class CylinderMask extends AbstractMask implements StaticMask {
028
029    private final double centerA;
030    private final double centerB;
031    private final double radiusSqA;
032    private final double radiusSqB;
033    private final boolean filled;
034    private final Direction.Axis alignment;
035
036    public CylinderMask(int widthX, int heightY, int lengthZ, boolean filled, Direction.Axis alignment) {
037        super(widthX, heightY, lengthZ);
038        this.centerA = this.getA(widthX, heightY, alignment) / 2.0;
039        this.centerB = this.getB(heightY, lengthZ, alignment) / 2.0;
040        this.radiusSqA = (this.centerA - 1) * (this.centerA - 1);
041        this.radiusSqB = (this.centerB - 1) * (this.centerB - 1);
042        this.filled = filled;
043        this.alignment = alignment;
044    }
045
046    @Override
047    public boolean partOfMask(int x, int y, int z) {
048        double da = Math.abs((this.getA(x, y, this.alignment) + 0.5) - this.centerA);
049        double db = Math.abs((this.getB(y, z, this.alignment) + 0.5) - this.centerB);
050        if (this.outside(da, db)) {
051            return false;
052        }
053        return this.filled
054                || this.outside(da + 1, db)
055                || this.outside(da, db + 1);
056    }
057
058    private boolean outside(double da, double db) {
059        return da * da / this.radiusSqA + db * db / this.radiusSqB > 1;
060    }
061
062    private static int getA(int x, int y, Direction.Axis alignment) {
063        return alignment == Direction.Axis.X ? y : x;
064    }
065
066    private static int getB(int y, int z, Direction.Axis alignment) {
067        return alignment == Direction.Axis.Z ? y : z;
068    }
069}