All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.integratedmodelling.engine.geospace.extents.Area Maven / Gradle / Ivy

The newest version!
/*******************************************************************************
 *  Copyright (C) 2007, 2014:
 *  
 *    - Ferdinando Villa 
 *    - integratedmodelling.org
 *    - any other authors listed in @author annotations
 *
 *    All rights reserved. This file is part of the k.LAB software suite,
 *    meant to enable modular, collaborative, integrated 
 *    development of interoperable data and model components. For
 *    details, see http://integratedmodelling.org.
 *    
 *    This program is free software; you can redistribute it and/or
 *    modify it under the terms of the Affero General Public License 
 *    Version 3 or any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but without any warranty; without even the implied warranty of
 *    merchantability or fitness for a particular purpose.  See the
 *    Affero General Public License for more details.
 *  
 *     You should have received a copy of the Affero General Public License
 *     along with this program; if not, write to the Free Software
 *     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *     The license is also available at: https://www.gnu.org/licenses/agpl.html
 *******************************************************************************/
package org.integratedmodelling.engine.geospace.extents;

import org.geotools.geometry.jts.ReferencedEnvelope;
import org.integratedmodelling.api.modelling.IExtent;
import org.integratedmodelling.engine.geospace.Geospace;
import org.integratedmodelling.engine.geospace.literals.ShapeValue;
import org.integratedmodelling.exceptions.KlabException;
import org.integratedmodelling.exceptions.KlabRuntimeException;
import org.integratedmodelling.exceptions.KlabValidationException;
import org.opengis.referencing.crs.CoordinateReferenceSystem;

import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Envelope;

public abstract class Area {

    ReferencedEnvelope        envelope = null;
    CoordinateReferenceSystem crs;

    public abstract ShapeValue getShape();

    protected Area() {
    }

    public Area(CoordinateReferenceSystem crs, double minx, double miny, double maxx, double maxy) {
        this.crs = crs;
        this.envelope = new ReferencedEnvelope(minx, maxx, miny, maxy, crs);
    }

    public Area(ShapeValue shape) {
        this.envelope = shape.getEnvelope();
        this.crs = shape.getCRS();
    }

    public CoordinateReferenceSystem getCRS() {
        return crs;
    }

    /**
     * Get an envelope where the X axis is always east-west.
     * @return the straightened envelope
     */
    public ReferencedEnvelope getEnvelope() {
        return envelope;
    }

    public ShapeValue getBoundingBox() {
        try {
            ReferencedEnvelope e = envelope.transform(Geospace.get().getDefaultCRS(), true, 10);
            return new ShapeValue(e);
        } catch (Exception e) {
            throw new KlabRuntimeException(e);
        }
    }

    public ShapeValue getCentroid() {
        return getBoundingBox().getCentroid();
    }

    public boolean contains(Coordinate c) {
        return envelope.contains(c);
    }

    //
    // /**
    // * Get the envelope with the same axis order of the passed CRS.
    // * @return
    // */
    // public ReferencedEnvelope getDefaultEnvelope(CoordinateReferenceSystem ocr) {
    //
    // ReferencedEnvelope ret = envelope;
    //
    // AxisDirection myOrder = crs.getCoordinateSystem().getAxis(0).getDirection();
    // AxisDirection otOrder = ocr.getCoordinateSystem().getAxis(0).getDirection();
    //
    // if (!otOrder.equals(myOrder)) {
    // /*
    // * swap x/y to obtain the right envelope according to the CRS
    // */
    // ret = new ReferencedEnvelope(
    // ret.getMinY(), ret.getMaxY(),
    // ret.getMinX(), ret.getMaxX(), crs);
    // }
    //
    // return ret;
    // }

    public double getNorth() {
        return envelope.getMaxY();
    }

    public double getWest() {
        return envelope.getMinX();
    }

    public double getSouth() {
        return envelope.getMinY();
    }

    public double getEast() {
        return envelope.getMaxX();
    }

    public double getEWExtent() {
        return envelope.getWidth();
    }

    public double getNSExtent() {
        return envelope.getHeight();
    }

    @Override
    public String toString() {
        return "areal-extent(" + envelope + "," + crs.getName() + ")";
    }

    /**
     * @deprecated
     */
    @Deprecated
    Object[] computeCommonExtent(IExtent extent) throws KlabException {

        if (!(extent instanceof Area))
            throw new KlabValidationException("areal extent " + this
                    + " cannot be merged with non-areal extent " + extent);

        Area orextent = this;
        Area otextent = (Area) extent;

        CoordinateReferenceSystem crs1 = orextent.getCRS();
        CoordinateReferenceSystem crs2 = otextent.getCRS();

        CoordinateReferenceSystem ccr = Geospace.chooseCRS(crs1, crs2);
        ReferencedEnvelope env1 = orextent.getEnvelope();
        ReferencedEnvelope env2 = otextent.getEnvelope();

        if (!(crs1.equals(crs2) && ccr.equals(crs1))) {

            /*
             * transformations will swap axes as required so we want the
             * envelopes with the CRS's axis order
             */
            env1 = orextent.getEnvelope();
            env2 = otextent.getEnvelope();

            try {
                /*
                 * transformations will return axes swapped to what CRS defines, and we 
                 * want them normalized back to east-west on x before we use them
                 */
                env1 = env1.transform(ccr, true, 10);
                env2 = env2.transform(ccr, true, 10);

            } catch (Exception e) {
                throw new KlabValidationException(e);
            }
        }

        /* 
         * At this point the two envelopes are in the same CRS and with east-west on the X axis.
         * Set a new envelope to the intersection of the original ones after reprojecting them to
         * the common crs. 
         */
        Envelope common = env1.intersection(env2);
        return new Object[] { orextent, otextent, ccr, common, env1, env2 };

    }

    public Area and(IExtent extent) throws KlabException {

        Object[] cc = computeCommonExtent(extent);

        Area orextent = (Area) cc[0];
        Area otextent = (Area) cc[1];
        CoordinateReferenceSystem ccr = (CoordinateReferenceSystem) cc[2];
        Envelope common = (Envelope) cc[3];
        Envelope orenvnorm = (Envelope) cc[4];
        Envelope otenvnorm = (Envelope) cc[5];

        /*
         * TODO intersection may be empty - this should be checked in createMergedExtent instead
         * of cursing here.
         */
        if (common.isNull()) {
            return null;
        }

        /**
         * send out to a virtual to create the appropriate areal extent with this envelope and CRS, 
         * adding whatever else we need to use it.
         */
        return createMergedExtent(orextent, otextent, ccr, common, orenvnorm, otenvnorm);
    }

    public Area constrain(IExtent extent) throws KlabException {

        Object[] cc = computeCommonExtent(extent);

        Area orextent = (Area) cc[0];
        Area otextent = (Area) cc[1];
        CoordinateReferenceSystem ccr = (CoordinateReferenceSystem) cc[2];
        Envelope common = (Envelope) cc[3];
        Envelope orenvnorm = (Envelope) cc[4];
        Envelope otenvnorm = (Envelope) cc[5];

        /*
         * TODO intersection may be empty - this should be checked in createMergedExtent instead
         * of cursing here.
         */
        if (common.isNull()) {
            return null;
        }

        /**
         * send out to a virtual to create the appropriate areal extent with this envelope and CRS, 
         * adding whatever else we need to use it.
         */
        return createConstrainedExtent(orextent, otextent, ccr, common, orenvnorm, otenvnorm);
    }

    /**
     * Does the actual work of merging with the extent, after merge() has ensured that the extents
     * are spatial and have a common intersection and crs.
     * 
     * @param orextent
     * @param otextent
     * @param ccr
     * @param common
     * @param otenvnorm 
     * @param orenvnorm 
     * @return
     * @throws KlabException 
     */
    protected abstract Area createMergedExtent(Area orextent, Area otextent, CoordinateReferenceSystem ccr, Envelope common, Envelope orenvnorm, Envelope otenvnorm)
            throws KlabException;

    /**
     * Does the actual work of merging with the extent, ensuring that the grain of the
     * extent is the same as that of the constraining extent. Called after merge() has ensured 
     * that the extents are spatial and have a common intersection and crs.
     * 
     * @param orextent
     * @param otextent
     * @param ccr
     * @param common
     * @param otenvnorm 
     * @param orenvnorm 
     * @return
     * @throws KlabException 
     */
    protected abstract Area createConstrainedExtent(Area orextent, Area otextent, CoordinateReferenceSystem ccr, Envelope common, Envelope orenvnorm, Envelope otenvnorm)
            throws KlabException;

    public boolean contains(Area e) throws KlabException {
        return getBoundingBox().getGeometry().contains(e.getBoundingBox().getGeometry());
    }

    public boolean overlaps(Area e) throws KlabException {
        return getBoundingBox().getGeometry().overlaps(e.getBoundingBox().getGeometry());
    }

    public boolean intersects(Area e) throws KlabException {
        return getBoundingBox().getGeometry().intersects(e.getBoundingBox().getGeometry());
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy