1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.replica.replicaisland;
18
19/**
20 * An Axis-Aligned rectangular collision volume.  This code treats other volumes as if they are
21 * also rectangles when calculating intersections.  Therefore certain types of intersections, such
22 * as sphere vs rectangle, may not be absolutely precise (in the case of a sphere vs a rectangle,
23 * for example, a new rectangle that fits the sphere is used to perform the intersection test, so
24 * there is some potential for false-positives at the corners).  However, for our purposes absolute
25 * precision isn't necessary, so this simple implementation is sufficient.
26 */
27public class AABoxCollisionVolume extends CollisionVolume {
28    private Vector2 mWidthHeight;
29    private Vector2 mBottomLeft;
30
31    public AABoxCollisionVolume(float offsetX, float offsetY, float width, float height) {
32        super();
33        mBottomLeft = new Vector2(offsetX, offsetY);
34        mWidthHeight = new Vector2(width, height);
35    }
36
37    public AABoxCollisionVolume(float offsetX, float offsetY, float width, float height,
38            int hit) {
39        super(hit);
40        mBottomLeft = new Vector2(offsetX, offsetY);
41        mWidthHeight = new Vector2(width, height);
42    }
43
44    @Override
45    public final float getMaxX() {
46        return mBottomLeft.x + mWidthHeight.x;
47    }
48
49    @Override
50    public final float getMinX() {
51        return mBottomLeft.x;
52    }
53
54    @Override
55    public final float getMaxY() {
56        return mBottomLeft.y + mWidthHeight.y;
57    }
58
59    @Override
60    public final float getMinY() {
61        return mBottomLeft.y;
62    }
63
64    /**
65     * Calculates the intersection of this volume and another, and returns true if the
66     * volumes intersect.  This test treats the other volume as an AABox.
67     * @param position The world position of this volume.
68     * @param other The volume to test for intersections.
69     * @param otherPosition The world position of the other volume.
70     * @return true if the volumes overlap, false otherwise.
71     */
72    @Override
73    public boolean intersects(Vector2 position, FlipInfo flip, CollisionVolume other,
74            Vector2 otherPosition, FlipInfo otherFlip) {
75        final float left = getMinXPosition(flip) + position.x;
76        final float right = getMaxXPosition(flip) + position.x;
77        final float bottom = getMinYPosition(flip) + position.y;
78        final float top = getMaxYPosition(flip) + position.y;
79
80        final float otherLeft = other.getMinXPosition(otherFlip) + otherPosition.x;
81        final float otherRight = other.getMaxXPosition(otherFlip) + otherPosition.x;
82        final float otherBottom = other.getMinYPosition(otherFlip) + otherPosition.y;
83        final float otherTop = other.getMaxYPosition(otherFlip) + otherPosition.y;
84
85        final boolean result = boxIntersect(left, right, top, bottom,
86                    otherLeft, otherRight, otherTop, otherBottom)
87                || boxIntersect(otherLeft, otherRight, otherTop, otherBottom,
88                    left, right, top, bottom);
89
90        return result;
91    }
92
93    /** Tests two axis-aligned boxes for overlap. */
94    private boolean boxIntersect(float left1, float right1, float top1, float bottom1,
95            float left2, float right2, float top2, float bottom2) {
96        final boolean horizontalIntersection = left1 < right2 && left2 < right1;
97        final boolean verticalIntersection = top1 > bottom2 && top2 > bottom1;
98        final boolean intersecting = horizontalIntersection && verticalIntersection;
99        return intersecting;
100    }
101
102    /** Increases the size of this volume as necessary to fit the passed volume. */
103    public void growBy(CollisionVolume other) {
104        final float maxX;
105        final float minX;
106
107        final float maxY;
108        final float minY;
109
110        if (mWidthHeight.length2() > 0) {
111            maxX = Math.max(getMaxX(), other.getMaxX());
112            minX = Math.max(getMinX(), other.getMinX());
113            maxY = Math.max(getMaxY(), other.getMaxY());
114            minY = Math.max(getMinY(), other.getMinY());
115        } else {
116            maxX = other.getMaxX();
117            minX = other.getMinX();
118            maxY = other.getMaxY();
119            minY = other.getMinY();
120        }
121        final float horizontalDelta = maxX - minX;
122        final float verticalDelta = maxY - minY;
123        mBottomLeft.set(minX, minY);
124        mWidthHeight.set(horizontalDelta, verticalDelta);
125    }
126
127}
128