    001package net.minecraft.util;
    002
    003public class AxisAlignedBB
    004{
    005    /** ThreadLocal AABBPool */
    006    private static final ThreadLocal theAABBLocalPool = new AABBLocalPool();
    007    public double minX;
    008    public double minY;
    009    public double minZ;
    010    public double maxX;
    011    public double maxY;
    012    public double maxZ;
    013
    014    /**
    015     * Returns a bounding box with the specified bounds. Args: minX, minY, minZ, maxX, maxY, maxZ
    016     */
    017    public static AxisAlignedBB getBoundingBox(double par0, double par2, double par4, double par6, double par8, double par10)
    018    {
    019        return new AxisAlignedBB(par0, par2, par4, par6, par8, par10);
    020    }
    021
    022    /**
    023     * Gets the ThreadLocal AABBPool
    024     */
    025    public static AABBPool getAABBPool()
    026    {
    027        return (AABBPool)theAABBLocalPool.get();
    028    }
    029
    030    protected AxisAlignedBB(double par1, double par3, double par5, double par7, double par9, double par11)
    031    {
    032        this.minX = par1;
    033        this.minY = par3;
    034        this.minZ = par5;
    035        this.maxX = par7;
    036        this.maxY = par9;
    037        this.maxZ = par11;
    038    }
    039
    040    /**
    041     * Sets the bounds of the bounding box. Args: minX, minY, minZ, maxX, maxY, maxZ
    042     */
    043    public AxisAlignedBB setBounds(double par1, double par3, double par5, double par7, double par9, double par11)
    044    {
    045        this.minX = par1;
    046        this.minY = par3;
    047        this.minZ = par5;
    048        this.maxX = par7;
    049        this.maxY = par9;
    050        this.maxZ = par11;
    051        return this;
    052    }
    053
    054    /**
    055     * Adds the coordinates to the bounding box extending it if the point lies outside the current ranges. Args: x, y, z
    056     */
    057    public AxisAlignedBB addCoord(double par1, double par3, double par5)
    058    {
    059        double d3 = this.minX;
    060        double d4 = this.minY;
    061        double d5 = this.minZ;
    062        double d6 = this.maxX;
    063        double d7 = this.maxY;
    064        double d8 = this.maxZ;
    065
    066        if (par1 < 0.0D)
    067        {
    068            d3 += par1;
    069        }
    070
    071        if (par1 > 0.0D)
    072        {
    073            d6 += par1;
    074        }
    075
    076        if (par3 < 0.0D)
    077        {
    078            d4 += par3;
    079        }
    080
    081        if (par3 > 0.0D)
    082        {
    083            d7 += par3;
    084        }
    085
    086        if (par5 < 0.0D)
    087        {
    088            d5 += par5;
    089        }
    090
    091        if (par5 > 0.0D)
    092        {
    093            d8 += par5;
    094        }
    095
    096        return getAABBPool().getAABB(d3, d4, d5, d6, d7, d8);
    097    }
    098
    099    /**
    100     * Returns a bounding box expanded by the specified vector (if negative numbers are given it will shrink). Args: x,
    101     * y, z
    102     */
    103    public AxisAlignedBB expand(double par1, double par3, double par5)
    104    {
    105        double d3 = this.minX - par1;
    106        double d4 = this.minY - par3;
    107        double d5 = this.minZ - par5;
    108        double d6 = this.maxX + par1;
    109        double d7 = this.maxY + par3;
    110        double d8 = this.maxZ + par5;
    111        return getAABBPool().getAABB(d3, d4, d5, d6, d7, d8);
    112    }
    113
    114    /**
    115     * Returns a bounding box offseted by the specified vector (if negative numbers are given it will shrink). Args: x,
    116     * y, z
    117     */
    118    public AxisAlignedBB getOffsetBoundingBox(double par1, double par3, double par5)
    119    {
    120        return getAABBPool().getAABB(this.minX + par1, this.minY + par3, this.minZ + par5, this.maxX + par1, this.maxY + par3, this.maxZ + par5);
    121    }
    122
    123    /**
    124     * if instance and the argument bounding boxes overlap in the Y and Z dimensions, calculate the offset between them
    125     * in the X dimension.  return var2 if the bounding boxes do not overlap or if var2 is closer to 0 then the
    126     * calculated offset.  Otherwise return the calculated offset.
    127     */
    128    public double calculateXOffset(AxisAlignedBB par1AxisAlignedBB, double par2)
    129    {
    130        if (par1AxisAlignedBB.maxY > this.minY && par1AxisAlignedBB.minY < this.maxY)
    131        {
    132            if (par1AxisAlignedBB.maxZ > this.minZ && par1AxisAlignedBB.minZ < this.maxZ)
    133            {
    134                double d1;
    135
    136                if (par2 > 0.0D && par1AxisAlignedBB.maxX <= this.minX)
    137                {
    138                    d1 = this.minX - par1AxisAlignedBB.maxX;
    139
    140                    if (d1 < par2)
    141                    {
    142                        par2 = d1;
    143                    }
    144                }
    145
    146                if (par2 < 0.0D && par1AxisAlignedBB.minX >= this.maxX)
    147                {
    148                    d1 = this.maxX - par1AxisAlignedBB.minX;
    149
    150                    if (d1 > par2)
    151                    {
    152                        par2 = d1;
    153                    }
    154                }
    155
    156                return par2;
    157            }
    158            else
    159            {
    160                return par2;
    161            }
    162        }
    163        else
    164        {
    165            return par2;
    166        }
    167    }
    168
    169    /**
    170     * if instance and the argument bounding boxes overlap in the X and Z dimensions, calculate the offset between them
    171     * in the Y dimension.  return var2 if the bounding boxes do not overlap or if var2 is closer to 0 then the
    172     * calculated offset.  Otherwise return the calculated offset.
    173     */
    174    public double calculateYOffset(AxisAlignedBB par1AxisAlignedBB, double par2)
    175    {
    176        if (par1AxisAlignedBB.maxX > this.minX && par1AxisAlignedBB.minX < this.maxX)
    177        {
    178            if (par1AxisAlignedBB.maxZ > this.minZ && par1AxisAlignedBB.minZ < this.maxZ)
    179            {
    180                double d1;
    181
    182                if (par2 > 0.0D && par1AxisAlignedBB.maxY <= this.minY)
    183                {
    184                    d1 = this.minY - par1AxisAlignedBB.maxY;
    185
    186                    if (d1 < par2)
    187                    {
    188                        par2 = d1;
    189                    }
    190                }
    191
    192                if (par2 < 0.0D && par1AxisAlignedBB.minY >= this.maxY)
    193                {
    194                    d1 = this.maxY - par1AxisAlignedBB.minY;
    195
    196                    if (d1 > par2)
    197                    {
    198                        par2 = d1;
    199                    }
    200                }
    201
    202                return par2;
    203            }
    204            else
    205            {
    206                return par2;
    207            }
    208        }
    209        else
    210        {
    211            return par2;
    212        }
    213    }
    214
    215    /**
    216     * if instance and the argument bounding boxes overlap in the Y and X dimensions, calculate the offset between them
    217     * in the Z dimension.  return var2 if the bounding boxes do not overlap or if var2 is closer to 0 then the
    218     * calculated offset.  Otherwise return the calculated offset.
    219     */
    220    public double calculateZOffset(AxisAlignedBB par1AxisAlignedBB, double par2)
    221    {
    222        if (par1AxisAlignedBB.maxX > this.minX && par1AxisAlignedBB.minX < this.maxX)
    223        {
    224            if (par1AxisAlignedBB.maxY > this.minY && par1AxisAlignedBB.minY < this.maxY)
    225            {
    226                double d1;
    227
    228                if (par2 > 0.0D && par1AxisAlignedBB.maxZ <= this.minZ)
    229                {
    230                    d1 = this.minZ - par1AxisAlignedBB.maxZ;
    231
    232                    if (d1 < par2)
    233                    {
    234                        par2 = d1;
    235                    }
    236                }
    237
    238                if (par2 < 0.0D && par1AxisAlignedBB.minZ >= this.maxZ)
    239                {
    240                    d1 = this.maxZ - par1AxisAlignedBB.minZ;
    241
    242                    if (d1 > par2)
    243                    {
    244                        par2 = d1;
    245                    }
    246                }
    247
    248                return par2;
    249            }
    250            else
    251            {
    252                return par2;
    253            }
    254        }
    255        else
    256        {
    257            return par2;
    258        }
    259    }
    260
    261    /**
    262     * Returns whether the given bounding box intersects with this one. Args: axisAlignedBB
    263     */
    264    public boolean intersectsWith(AxisAlignedBB par1AxisAlignedBB)
    265    {
    266        return par1AxisAlignedBB.maxX > this.minX && par1AxisAlignedBB.minX < this.maxX ? (par1AxisAlignedBB.maxY > this.minY && par1AxisAlignedBB.minY < this.maxY ? par1AxisAlignedBB.maxZ > this.minZ && par1AxisAlignedBB.minZ < this.maxZ : false) : false;
    267    }
    268
    269    /**
    270     * Offsets the current bounding box by the specified coordinates. Args: x, y, z
    271     */
    272    public AxisAlignedBB offset(double par1, double par3, double par5)
    273    {
    274        this.minX += par1;
    275        this.minY += par3;
    276        this.minZ += par5;
    277        this.maxX += par1;
    278        this.maxY += par3;
    279        this.maxZ += par5;
    280        return this;
    281    }
    282
    283    /**
    284     * Returns if the supplied Vec3D is completely inside the bounding box
    285     */
    286    public boolean isVecInside(Vec3 par1Vec3)
    287    {
    288        return par1Vec3.xCoord > this.minX && par1Vec3.xCoord < this.maxX ? (par1Vec3.yCoord > this.minY && par1Vec3.yCoord < this.maxY ? par1Vec3.zCoord > this.minZ && par1Vec3.zCoord < this.maxZ : false) : false;
    289    }
    290
    291    /**
    292     * Returns the average length of the edges of the bounding box.
    293     */
    294    public double getAverageEdgeLength()
    295    {
    296        double d0 = this.maxX - this.minX;
    297        double d1 = this.maxY - this.minY;
    298        double d2 = this.maxZ - this.minZ;
    299        return (d0 + d1 + d2) / 3.0D;
    300    }
    301
    302    /**
    303     * Returns a bounding box that is inset by the specified amounts
    304     */
    305    public AxisAlignedBB contract(double par1, double par3, double par5)
    306    {
    307        double d3 = this.minX + par1;
    308        double d4 = this.minY + par3;
    309        double d5 = this.minZ + par5;
    310        double d6 = this.maxX - par1;
    311        double d7 = this.maxY - par3;
    312        double d8 = this.maxZ - par5;
    313        return getAABBPool().getAABB(d3, d4, d5, d6, d7, d8);
    314    }
    315
    316    /**
    317     * Returns a copy of the bounding box.
    318     */
    319    public AxisAlignedBB copy()
    320    {
    321        return getAABBPool().getAABB(this.minX, this.minY, this.minZ, this.maxX, this.maxY, this.maxZ);
    322    }
    323
    324    public MovingObjectPosition calculateIntercept(Vec3 par1Vec3, Vec3 par2Vec3)
    325    {
    326        Vec3 vec32 = par1Vec3.getIntermediateWithXValue(par2Vec3, this.minX);
    327        Vec3 vec33 = par1Vec3.getIntermediateWithXValue(par2Vec3, this.maxX);
    328        Vec3 vec34 = par1Vec3.getIntermediateWithYValue(par2Vec3, this.minY);
    329        Vec3 vec35 = par1Vec3.getIntermediateWithYValue(par2Vec3, this.maxY);
    330        Vec3 vec36 = par1Vec3.getIntermediateWithZValue(par2Vec3, this.minZ);
    331        Vec3 vec37 = par1Vec3.getIntermediateWithZValue(par2Vec3, this.maxZ);
    332
    333        if (!this.isVecInYZ(vec32))
    334        {
    335            vec32 = null;
    336        }
    337
    338        if (!this.isVecInYZ(vec33))
    339        {
    340            vec33 = null;
    341        }
    342
    343        if (!this.isVecInXZ(vec34))
    344        {
    345            vec34 = null;
    346        }
    347
    348        if (!this.isVecInXZ(vec35))
    349        {
    350            vec35 = null;
    351        }
    352
    353        if (!this.isVecInXY(vec36))
    354        {
    355            vec36 = null;
    356        }
    357
    358        if (!this.isVecInXY(vec37))
    359        {
    360            vec37 = null;
    361        }
    362
    363        Vec3 vec38 = null;
    364
    365        if (vec32 != null && (vec38 == null || par1Vec3.squareDistanceTo(vec32) < par1Vec3.squareDistanceTo(vec38)))
    366        {
    367            vec38 = vec32;
    368        }
    369
    370        if (vec33 != null && (vec38 == null || par1Vec3.squareDistanceTo(vec33) < par1Vec3.squareDistanceTo(vec38)))
    371        {
    372            vec38 = vec33;
    373        }
    374
    375        if (vec34 != null && (vec38 == null || par1Vec3.squareDistanceTo(vec34) < par1Vec3.squareDistanceTo(vec38)))
    376        {
    377            vec38 = vec34;
    378        }
    379
    380        if (vec35 != null && (vec38 == null || par1Vec3.squareDistanceTo(vec35) < par1Vec3.squareDistanceTo(vec38)))
    381        {
    382            vec38 = vec35;
    383        }
    384
    385        if (vec36 != null && (vec38 == null || par1Vec3.squareDistanceTo(vec36) < par1Vec3.squareDistanceTo(vec38)))
    386        {
    387            vec38 = vec36;
    388        }
    389
    390        if (vec37 != null && (vec38 == null || par1Vec3.squareDistanceTo(vec37) < par1Vec3.squareDistanceTo(vec38)))
    391        {
    392            vec38 = vec37;
    393        }
    394
    395        if (vec38 == null)
    396        {
    397            return null;
    398        }
    399        else
    400        {
    401            byte b0 = -1;
    402
    403            if (vec38 == vec32)
    404            {
    405                b0 = 4;
    406            }
    407
    408            if (vec38 == vec33)
    409            {
    410                b0 = 5;
    411            }
    412
    413            if (vec38 == vec34)
    414            {
    415                b0 = 0;
    416            }
    417
    418            if (vec38 == vec35)
    419            {
    420                b0 = 1;
    421            }
    422
    423            if (vec38 == vec36)
    424            {
    425                b0 = 2;
    426            }
    427
    428            if (vec38 == vec37)
    429            {
    430                b0 = 3;
    431            }
    432
    433            return new MovingObjectPosition(0, 0, 0, b0, vec38);
    434        }
    435    }
    436
    437    /**
    438     * Checks if the specified vector is within the YZ dimensions of the bounding box. Args: Vec3D
    439     */
    440    private boolean isVecInYZ(Vec3 par1Vec3)
    441    {
    442        return par1Vec3 == null ? false : par1Vec3.yCoord >= this.minY && par1Vec3.yCoord <= this.maxY && par1Vec3.zCoord >= this.minZ && par1Vec3.zCoord <= this.maxZ;
    443    }
    444
    445    /**
    446     * Checks if the specified vector is within the XZ dimensions of the bounding box. Args: Vec3D
    447     */
    448    private boolean isVecInXZ(Vec3 par1Vec3)
    449    {
    450        return par1Vec3 == null ? false : par1Vec3.xCoord >= this.minX && par1Vec3.xCoord <= this.maxX && par1Vec3.zCoord >= this.minZ && par1Vec3.zCoord <= this.maxZ;
    451    }
    452
    453    /**
    454     * Checks if the specified vector is within the XY dimensions of the bounding box. Args: Vec3D
    455     */
    456    private boolean isVecInXY(Vec3 par1Vec3)
    457    {
    458        return par1Vec3 == null ? false : par1Vec3.xCoord >= this.minX && par1Vec3.xCoord <= this.maxX && par1Vec3.yCoord >= this.minY && par1Vec3.yCoord <= this.maxY;
    459    }
    460
    461    /**
    462     * Sets the bounding box to the same bounds as the bounding box passed in. Args: axisAlignedBB
    463     */
    464    public void setBB(AxisAlignedBB par1AxisAlignedBB)
    465    {
    466        this.minX = par1AxisAlignedBB.minX;
    467        this.minY = par1AxisAlignedBB.minY;
    468        this.minZ = par1AxisAlignedBB.minZ;
    469        this.maxX = par1AxisAlignedBB.maxX;
    470        this.maxY = par1AxisAlignedBB.maxY;
    471        this.maxZ = par1AxisAlignedBB.maxZ;
    472    }
    473
    474    public String toString()
    475    {
    476        return "box[" + this.minX + ", " + this.minY + ", " + this.minZ + " -> " + this.maxX + ", " + this.maxY + ", " + this.maxZ + "]";
    477    }
    478}