org.mrgeo.utils.Bounds.java Source code

Java tutorial

Introduction

Here is the source code for org.mrgeo.utils.Bounds.java

Source

/*
 * Copyright 2009-2014 DigitalGlobe, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and limitations under the License.
 */

package org.mrgeo.utils;

import com.vividsolutions.jts.geom.Envelope;
import org.apache.commons.lang.NotImplementedException;
import org.codehaus.jackson.annotate.JsonIgnore;

import java.awt.geom.Rectangle2D;
import java.io.Serializable;

/**
 * @author jason.surratt
 * 
 */

// NOTE: This class is json serialized, so there are @JsonIgnore annotations on the
//       getters/setters that should not be automatically serialized
//
// NOTE:  Because of the json serialization, we'll call individual setters on 
//        initialization.  That means we need to keep track of what setters have 
//        been called, and update the <set> value when all 4 are called.  That's
//        what the <individualParamSet> is for.
public class Bounds implements Comparable<Bounds>, Serializable {
    private static final long serialVersionUID = 1L;

    public static final Bounds world = new Bounds(-180, -90, 180, 90);

    private double minX, minY, maxX, maxY;
    private boolean set = false;

    private int individualParamSet = 0;

    public Bounds() {
        clear();
    }

    public Bounds(double[] ary) {
        this.minX = ary[0];
        this.minY = ary[1];
        this.maxX = ary[2];
        this.maxY = ary[3];

        set = true;
    }

    public Bounds(double minX, double minY, double maxX, double maxY) {
        this.minX = minX;
        this.minY = minY;
        this.maxX = maxX;
        this.maxY = maxY;

        set = true;
    }

    public Bounds(Rectangle2D from) {
        minX = from.getMinX();
        minY = from.getMinY();
        maxX = from.getMaxX();
        maxY = from.getMaxY();

        set = true;
    }

    public Bounds(String boundsStr) {
        //expects comma delimited, no spaces: minX,minY,maxX,maxY; e.g. "-115,30,-95,50"
        String[] boundsParts = boundsStr.split(",");
        this.minX = Double.parseDouble(boundsParts[0]);
        this.minY = Double.parseDouble(boundsParts[1]);
        this.maxX = Double.parseDouble(boundsParts[2]);
        this.maxY = Double.parseDouble(boundsParts[3]);

        set = true;
    }

    @Override
    public Bounds clone() {
        return new Bounds(minX, minY, maxX, maxY);
    }

    @Override
    public int compareTo(Bounds o) {
        if (minX < o.minX) {
            return -1;
        } else if (minX == o.minX) {
            return Double.compare(minY, o.minY);
        }

        return 1;
    }

    @Override
    public boolean equals(Object obj) {
        boolean result = false;
        if (obj instanceof Bounds) {
            Bounds other = (Bounds) obj;
            result = minX == other.minX && minY == other.minY && maxX == other.maxX && maxY == other.maxY;
        }
        return result;
    }

    public void expand(Bounds b) {
        if (!set) {
            if (b.isValid()) {
                minX = b.minX;
                minY = b.minY;
                maxX = b.maxX;
                maxY = b.maxY;

                set = true;
            }
        } else {
            minX = Math.min(b.minX, minX);
            minY = Math.min(b.minY, minY);
            maxX = Math.max(b.maxX, maxX);
            maxY = Math.max(b.maxY, maxY);
        }
    }

    public void expand(final double xMin, final double yMin, final double xMax, final double yMax) {
        if (!set) {
            minX = xMin;
            minY = yMin;
            maxX = xMax;
            maxY = yMax;

            set = true;
        } else {
            minX = Math.min(xMin, minX);
            minY = Math.min(yMin, minY);
            maxX = Math.max(xMax, maxX);
            maxY = Math.max(yMax, maxY);
        }
    }

    public void expand(double x, double y) {
        if (!set) {
            minX = x;
            minY = y;
            maxX = x;
            maxY = y;

            set = true;
        } else {
            minX = Math.min(x, minX);
            minY = Math.min(y, minY);
            maxX = Math.max(x, maxX);
            maxY = Math.max(y, maxY);
        }
    }

    @JsonIgnore
    public TMSUtils.Bounds getTMSBounds() {
        return new TMSUtils.Bounds(minX, minY, maxX, maxY);
    }

    @JsonIgnore
    public double getCenterX() {
        return (minX + maxX) / 2.0;
    }

    @JsonIgnore
    public double getCenterY() {
        return (minY + maxY) / 2.0;
    }

    @JsonIgnore
    public double getHeight() {
        return maxY - minY;
    }

    public double getMaxX() {
        return maxX;
    }

    public double getMaxY() {
        return maxY;
    }

    public double getMinX() {
        return minX;
    }

    public double getMinY() {
        return minY;
    }

    @JsonIgnore
    public double getWidth() {
        return maxX - minX;
    }

    public void clear() {
        minX = Double.MAX_VALUE;
        minY = Double.MAX_VALUE;
        maxX = -Double.MAX_VALUE;
        maxY = -Double.MAX_VALUE;
    }

    @JsonIgnore
    public boolean isValid() {
        return (set && (minX != Double.MAX_VALUE) && (minY != Double.MAX_VALUE) && (maxX != -Double.MAX_VALUE)
                && (maxY != -Double.MAX_VALUE));
    }

    public boolean intersects(final double srcMinX, final double srcMinY, final double srcMaxX,
            final double srcMaxY) {
        return intersects(new Bounds(srcMinX, srcMinY, srcMaxX, srcMaxY));
    }

    public boolean intersects(final Bounds b) {
        // formula:
        // x, y are center points of the rectangle...
        //
        //    if Math.abs(rectA.x - rectB.x) < (Math.abs(rectA.width + rectB.width) / 2) 
        //      && (Math.abs(rectA.y - rectB.y) < (Math.abs(rectA.height + rectB.height) / 2))
        //    then
        //        // A and B collide
        //    end if

        return (Math.abs(getCenterX() - b.getCenterX()) < Math.abs(getWidth() + b.getWidth()) / 2)
                && (Math.abs(getCenterY() - b.getCenterY()) < Math.abs(getHeight() + b.getHeight()) / 2);
    }

    @SuppressWarnings({ "unused", "static-method" })
    public boolean intersectsLine(final double x1, final double y1, final double x2, final double y2) {
        throw new NotImplementedException();
    }

    public boolean containsPoint(final double x, final double y) {
        return (x >= getMinX() && x <= getMaxX() && y >= getMinY() && y <= getMaxY());
    }

    public boolean contains(Bounds b) {
        return contains(b, true);
    }

    public boolean contains(final Bounds b, final boolean includeAdjacent) {
        if (includeAdjacent) {
            return (b.minX >= minX && b.minY >= minY && b.maxX <= maxX && b.maxY <= maxY);
        }
        return (b.minX > minX && b.minY > minY && b.maxX < maxX && b.maxY < maxY);
    }

    /**
     * Return the intersection of this bounds with b.
     */
    public Bounds intersection(Bounds b) {
        return new Bounds(Math.max(minX, b.minX), Math.max(minY, b.minY), Math.min(maxX, b.maxX),
                Math.min(maxY, b.maxY));
    }

    public void setMaxX(double maxX) {
        individualParamSet |= 1;
        set = set | individualParamSet == 15;

        this.maxX = maxX;
    }

    public void setMaxY(double maxY) {
        individualParamSet |= 2;
        set = set | individualParamSet == 15;

        this.maxY = maxY;
    }

    public void setMinX(double minX) {
        individualParamSet |= 4;
        set = set | individualParamSet == 15;

        this.minX = minX;
    }

    public void setMinY(double minY) {
        individualParamSet |= 8;
        set = set | individualParamSet == 15;

        this.minY = minY;
    }

    public Envelope toEnvelope() {
        return new Envelope(minX, maxX, minY, maxY);
    }

    public Rectangle2D.Double toRectangle2D() {
        return new Rectangle2D.Double(minX, minY, getWidth(), getHeight());
    }

    @Override
    public String toString() {
        return "Bounds: lon/lat" + "(" + minX + "," + minY + ") (" + maxX + "," + maxY + ")";
    }

    @Override
    public int hashCode() {
        return super.hashCode();
    }

    public static Bounds fromDelimitedString(final String rect) {
        String[] args = rect.split(",");
        if (args.length != 4) {
            throw new IllegalArgumentException(
                    "Delimited Bounds should be in the format of \"minx,miny,maxx,maxy\" (delimited by \",\") ");
        }

        return new Bounds(Double.parseDouble(args[0]), Double.parseDouble(args[1]), Double.parseDouble(args[2]),
                Double.parseDouble(args[3]));
    }

    public String toDelimitedString() {
        // Don't use String.format - it's slow and loses precision apparently
        return "" + Double.valueOf(minX) + "," + Double.valueOf(minY) + "," + Double.valueOf(maxX) + ","
                + Double.valueOf(maxY);
    }
}