1255 lines · 42.3 KB · Java
RawDownload
     * Region object if no clipping occurs.     */    public Region getIntersection(Region r) {        if (this.isInsideQuickCheck(r)) {            return this;        }        if (r.isInsideQuickCheck(this)) {            return r;        }        Region ret = new Region((r.lox < this.lox) ? this.lox : r.lox,                                (r.loy < this.loy) ? this.loy : r.loy,                                (r.hix > this.hix) ? this.hix : r.hix,                                (r.hiy > this.hiy) ? this.hiy : r.hiy);        if (!ret.isEmpty()) {            ret.filterSpans(this, r, INCLUDE_COMMON);        }        return ret;    }     /**     * Returns a Region object that represents the union of this     * object with the specified Region object.     * <p>     * If {@code A} and {@code B} are both Region Objects and     * <code>C = A.getUnion(B);</code> then a point will     * be contained in {@code C} iff it is contained in either     * {@code A} or {@code B}.     * <p>     * The return value may be this same object or the argument     * Region object if no augmentation occurs.     */    public Region getUnion(Region r) {        if (r.isEmpty() || r.isInsideQuickCheck(this)) {            return this;        }        if (this.isEmpty() || this.isInsideQuickCheck(r)) {            return r;        }        Region ret = new Region((r.lox > this.lox) ? this.lox : r.lox,                                (r.loy > this.loy) ? this.loy : r.loy,                                (r.hix < this.hix) ? this.hix : r.hix,                                (r.hiy < this.hiy) ? this.hiy : r.hiy);        ret.filterSpans(this, r, INCLUDE_A | INCLUDE_B | INCLUDE_COMMON);        return ret;    }     /**     * Returns a Region object that represents the difference of the     * specified Region object subtracted from this object.     * <p>     * If {@code A} and {@code B} are both Region Objects and     * <code>C = A.getDifference(B);</code> then a point will     * be contained in {@code C} iff it is contained in     * {@code A} but not contained in {@code B}.     * <p>     * The return value may be this same object or the argument     * Region object if no clipping occurs.     */    public Region getDifference(Region r) {        if (!r.intersectsQuickCheck(this)) {            return this;        }        if (this.isInsideQuickCheck(r)) {            return EMPTY_REGION;        }        Region ret = new Region(this.lox, this.loy, this.hix, this.hiy);        ret.filterSpans(this, r, INCLUDE_A);        return ret;    }     /**     * Returns a Region object that represents the exclusive or of this     * object with the specified Region object.     * <p>     * If {@code A} and {@code B} are both Region Objects and     * <code>C = A.getExclusiveOr(B);</code> then a point will     * be contained in {@code C} iff it is contained in either     * {@code A} or {@code B}, but not if it is contained in both.     * <p>     * The return value may be this same object or the argument     * Region object if either is empty.     */    public Region getExclusiveOr(Region r) {        if (r.isEmpty()) {            return this;        }        if (this.isEmpty()) {            return r;        }        Region ret = new Region((r.lox > this.lox) ? this.lox : r.lox,                                (r.loy > this.loy) ? this.loy : r.loy,                                (r.hix < this.hix) ? this.hix : r.hix,                                (r.hiy < this.hiy) ? this.hiy : r.hiy);        ret.filterSpans(this, r, INCLUDE_A | INCLUDE_B);        return ret;    }     static final int INCLUDE_A      = 1;    static final int INCLUDE_B      = 2;    static final int INCLUDE_COMMON = 4;     private void filterSpans(Region ra, Region rb, int flags) {        int abands[] = ra.bands;        int bbands[] = rb.bands;        if (abands == null) {            abands = new int[] {ra.loy, ra.hiy, 1, ra.lox, ra.hix};        }        if (bbands == null) {            bbands = new int[] {rb.loy, rb.hiy, 1, rb.lox, rb.hix};        }        int box[] = new int[6];        int acolstart = 0;        int ay1 = abands[acolstart++];        int ay2 = abands[acolstart++];        int acolend = abands[acolstart++];        acolend = acolstart + 2 * acolend;        int bcolstart = 0;        int by1 = bbands[bcolstart++];        int by2 = bbands[bcolstart++];        int bcolend = bbands[bcolstart++];        bcolend = bcolstart + 2 * bcolend;        int y = loy;        while (y < hiy) {            if (y >= ay2) {                if (acolend < ra.endIndex) {                    acolstart = acolend;                    ay1 = abands[acolstart++];                    ay2 = abands[acolstart++];                    acolend = abands[acolstart++];                    acolend = acolstart + 2 * acolend;                } else {                    if ((flags & INCLUDE_B) == 0) break;                    ay1 = ay2 = hiy;                }                continue;            }            if (y >= by2) {                if (bcolend < rb.endIndex) {                    bcolstart = bcolend;                    by1 = bbands[bcolstart++];                    by2 = bbands[bcolstart++];                    bcolend = bbands[bcolstart++];                    bcolend = bcolstart + 2 * bcolend;                } else {                    if ((flags & INCLUDE_A) == 0) break;                    by1 = by2 = hiy;                }                continue;            }            int yend;            if (y < by1) {                if (y < ay1) {                    y = Math.min(ay1, by1);                    continue;                }                // We are in a set of rows that belong only to A                yend = Math.min(ay2, by1);                if ((flags & INCLUDE_A) != 0) {                    box[1] = y;                    box[3] = yend;                    int acol = acolstart;                    while (acol < acolend) {                        box[0] = abands[acol++];                        box[2] = abands[acol++];                        appendSpan(box);                    }                }            } else if (y < ay1) {                // We are in a set of rows that belong only to B                yend = Math.min(by2, ay1);                if ((flags & INCLUDE_B) != 0) {                    box[1] = y;                    box[3] = yend;                    int bcol = bcolstart;                    while (bcol < bcolend) {                        box[0] = bbands[bcol++];                        box[2] = bbands[bcol++];                        appendSpan(box);                    }                }            } else {                // We are in a set of rows that belong to both A and B                yend = Math.min(ay2, by2);                box[1] = y;                box[3] = yend;                int acol = acolstart;                int bcol = bcolstart;                int ax1 = abands[acol++];                int ax2 = abands[acol++];                int bx1 = bbands[bcol++];                int bx2 = bbands[bcol++];                int x = Math.min(ax1, bx1);                if (x < lox) x = lox;                while (x < hix) {                    if (x >= ax2) {                        if (acol < acolend) {                            ax1 = abands[acol++];                            ax2 = abands[acol++];                        } else {                            if ((flags & INCLUDE_B) == 0) break;                            ax1 = ax2 = hix;                        }                        continue;                    }                    if (x >= bx2) {                        if (bcol < bcolend) {                            bx1 = bbands[bcol++];                            bx2 = bbands[bcol++];                        } else {                            if ((flags & INCLUDE_A) == 0) break;                            bx1 = bx2 = hix;                        }                        continue;                    }                    int xend;                    boolean appendit;                    if (x < bx1) {                        if (x < ax1) {                            xend = Math.min(ax1, bx1);                            appendit = false;                        } else {                            xend = Math.min(ax2, bx1);                            appendit = ((flags & INCLUDE_A) != 0);                        }                    } else if (x < ax1) {                        xend = Math.min(ax1, bx2);                        appendit = ((flags & INCLUDE_B) != 0);                    } else {                        xend = Math.min(ax2, bx2);                        appendit = ((flags & INCLUDE_COMMON) != 0);                    }                    if (appendit) {                        box[0] = x;                        box[2] = xend;                        appendSpan(box);                    }                    x = xend;                }            }            y = yend;        }        endRow(box);        calcBBox();    }     /**     * Returns a Region object that represents the bounds of the     * intersection of this object with the bounds of the specified     * Region object.     * <p>     * The return value may be this same object if no clipping occurs     * and this Region is rectangular.     */    public Region getBoundsIntersection(Rectangle r) {        return getBoundsIntersectionXYWH(r.x, r.y, r.width, r.height);    }     /**     * Returns a Region object that represents the bounds of the     * intersection of this object with the bounds of the specified     * rectangular area in x, y, width, height format.     * <p>     * The return value may be this same object if no clipping occurs     * and this Region is rectangular.     */    public Region getBoundsIntersectionXYWH(int x, int y, int w, int h) {        return getBoundsIntersectionXYXY(x, y, dimAdd(x, w), dimAdd(y, h));    }     /**     * Returns a Region object that represents the bounds of the     * intersection of this object with the bounds of the specified     * rectangular area in lox, loy, hix, hiy format.     * <p>     * The return value may be this same object if no clipping occurs     * and this Region is rectangular.     */    public Region getBoundsIntersectionXYXY(int lox, int loy,                                            int hix, int hiy)    {        if (this.bands == null &&            this.lox >= lox && this.loy >= loy &&            this.hix <= hix && this.hiy <= hiy)        {            return this;        }        return new Region((lox < this.lox) ? this.lox : lox,                          (loy < this.loy) ? this.loy : loy,                          (hix > this.hix) ? this.hix : hix,                          (hiy > this.hiy) ? this.hiy : hiy);    }     /**     * Returns a Region object that represents the intersection of     * this object with the bounds of the specified Region object.     * <p>     * The return value may be this same object or the argument     * Region object if no clipping occurs and the Regions are     * rectangular.     */    public Region getBoundsIntersection(Region r) {        if (this.encompasses(r)) {            return r;        }        if (r.encompasses(this)) {            return this;        }        return new Region((r.lox < this.lox) ? this.lox : r.lox,                          (r.loy < this.loy) ? this.loy : r.loy,                          (r.hix > this.hix) ? this.hix : r.hix,                          (r.hiy > this.hiy) ? this.hiy : r.hiy);    }     /**     * Appends a single span defined by the 4 parameters     * spanlox, spanloy, spanhix, spanhiy.     * This span must be at a higher starting Y coordinate than     * the previous data or it must have a Y range equal to the     * highest Y band in the region and a higher X coordinate     * than any of the spans in that band.     */    private void appendSpan(int box[]) {        int spanlox, spanloy, spanhix, spanhiy;        if ((spanlox = box[0]) < lox) spanlox = lox;        if ((spanloy = box[1]) < loy) spanloy = loy;        if ((spanhix = box[2]) > hix) spanhix = hix;        if ((spanhiy = box[3]) > hiy) spanhiy = hiy;        if (spanhix <= spanlox || spanhiy <= spanloy) {            return;        }         int curYrow = box[4];        if (endIndex == 0 || spanloy >= bands[curYrow + 1]) {            if (bands == null) {                bands = new int[INIT_SIZE];            } else {                needSpace(5);                endRow(box);                curYrow = box[4];            }            bands[endIndex++] = spanloy;            bands[endIndex++] = spanhiy;            bands[endIndex++] = 0;        } else if (spanloy == bands[curYrow] &&                   spanhiy == bands[curYrow + 1] &&                   spanlox >= bands[endIndex - 1]) {            if (spanlox == bands[endIndex - 1]) {                bands[endIndex - 1] = spanhix;                return;            }            needSpace(2);        } else {            throw new InternalError("bad span");        }        bands[endIndex++] = spanlox;        bands[endIndex++] = spanhix;        bands[curYrow + 2]++;    }     private void needSpace(int num) {        if (endIndex + num >= bands.length) {            int[] newbands = new int[bands.length + GROW_SIZE];            System.arraycopy(bands, 0, newbands, 0, endIndex);            bands = newbands;        }    }     private void endRow(int box[]) {        int cur = box[4];        int prev = box[5];        if (cur > prev) {            int[] bands = this.bands;            if (bands[prev + 1] == bands[cur] &&                bands[prev + 2] == bands[cur + 2])            {                int num = bands[cur + 2] * 2;                cur += 3;                prev += 3;                while (num > 0) {                    if (bands[cur++] != bands[prev++]) {                        break;                    }                    num--;                }                if (num == 0) {                    // prev == box[4]                    bands[box[5] + 1] = bands[prev + 1];                    endIndex = prev;                    return;                }            }        }        box[5] = box[4];        box[4] = endIndex;    }     private void calcBBox() {        int[] bands = this.bands;        if (endIndex <= 5) {            if (endIndex == 0) {                lox = loy = hix = hiy = 0;            } else {                loy = bands[0];                hiy = bands[1];                lox = bands[3];                hix = bands[4];                endIndex = 0;            }            this.bands = null;            return;        }        int lox = this.hix;        int hix = this.lox;        int hiyindex = 0;         int i = 0;        while (i < endIndex) {            hiyindex = i;            int numbands = bands[i + 2];            i += 3;            if (lox > bands[i]) {                lox = bands[i];            }            i += numbands * 2;            if (hix < bands[i - 1]) {                hix = bands[i - 1];            }        }         this.lox = lox;        this.loy = bands[0];        this.hix = hix;        this.hiy = bands[hiyindex + 1];    }     /**     * Returns the lowest X coordinate in the Region.     */    public final int getLoX() {        return lox;    }     /**     * Returns the lowest Y coordinate in the Region.     */    public final int getLoY() {        return loy;    }     /**     * Returns the highest X coordinate in the Region.     */    public final int getHiX() {        return hix;    }     /**     * Returns the highest Y coordinate in the Region.     */    public final int getHiY() {        return hiy;    }     /**     * Returns the width of this Region clipped to the range (0 - MAX_INT).     */    public final int getWidth() {        if (hix < lox) return 0;        int w;        if ((w = hix - lox) < 0) {            w = Integer.MAX_VALUE;        }        return w;    }     /**     * Returns the height of this Region clipped to the range (0 - MAX_INT).     */    public final int getHeight() {        if (hiy < loy) return 0;        int h;        if ((h = hiy - loy) < 0) {            h = Integer.MAX_VALUE;        }        return h;    }     /**     * Returns true iff this Region encloses no area.     */    public boolean isEmpty() {        return (hix <= lox || hiy <= loy);    }     /**     * Returns true iff this Region represents a single simple     * rectangular area.     */    public boolean isRectangular() {        return (bands == null);

Lines 501–1000 of 1255. Previous lines