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());
}
}