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

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

The newest version!
/*******************************************************************************
 * Copyright (C) 2007, 2015:
 * 
 * - 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 java.util.BitSet;
import java.util.Iterator;

import org.geotools.geometry.jts.ReferencedEnvelope;
import org.integratedmodelling.api.knowledge.IConcept;
import org.integratedmodelling.api.metadata.IMetadata;
import org.integratedmodelling.api.modelling.IExtent;
import org.integratedmodelling.api.modelling.IModelBean;
import org.integratedmodelling.api.modelling.IObservableSemantics;
import org.integratedmodelling.api.modelling.IObserver;
import org.integratedmodelling.api.modelling.IScale;
import org.integratedmodelling.api.modelling.IScale.Index;
import org.integratedmodelling.api.modelling.IScale.Locator;
import org.integratedmodelling.api.modelling.ITopologicallyComparable;
import org.integratedmodelling.api.modelling.storage.IStorage;
import org.integratedmodelling.api.space.IGrid;
import org.integratedmodelling.api.space.IShape;
import org.integratedmodelling.api.space.ISpatialExtent;
import org.integratedmodelling.api.space.ISpatialIndex;
import org.integratedmodelling.api.space.ITessellation;
import org.integratedmodelling.api.time.ITemporalExtent;
import org.integratedmodelling.collections.Pair;
import org.integratedmodelling.collections.Path;
import org.integratedmodelling.common.configuration.KLAB;
import org.integratedmodelling.common.interfaces.NetworkDeserializable;
import org.integratedmodelling.common.interfaces.NetworkSerializable;
import org.integratedmodelling.common.knowledge.Observation;
import org.integratedmodelling.common.model.runtime.Space;
import org.integratedmodelling.common.space.IGeometricShape;
import org.integratedmodelling.common.space.SpaceLocator;
import org.integratedmodelling.common.vocabulary.NS;
import org.integratedmodelling.engine.geospace.Geospace;
import org.integratedmodelling.engine.geospace.coverage.raster.RasterActivationLayer;
import org.integratedmodelling.engine.geospace.coverage.vector.VectorCoverage;
import org.integratedmodelling.engine.geospace.literals.ShapeValue;
import org.integratedmodelling.engine.modelling.runtime.mediators.GridToGrid;
import org.integratedmodelling.engine.modelling.runtime.mediators.GridToShape;
import org.integratedmodelling.engine.modelling.runtime.mediators.ShapeToGrid;
import org.integratedmodelling.engine.modelling.runtime.mediators.ShapeToShape;
import org.integratedmodelling.exceptions.KlabException;
import org.integratedmodelling.exceptions.KlabInternalErrorException;
import org.integratedmodelling.exceptions.KlabInternalRuntimeException;
import org.integratedmodelling.exceptions.KlabRuntimeException;
import org.integratedmodelling.exceptions.KlabUnsupportedOperationException;
import org.integratedmodelling.exceptions.KlabValidationException;
import org.opengis.referencing.crs.CoordinateReferenceSystem;

import com.vividsolutions.jts.geom.Geometry;

/**
 * Slated to substitute all other spatial extents - defines itself to the optimal
 * representation by merging other partially specified ones.
 * 
 * @author Ferd
 *
 */
public class SpaceExtent extends Observation implements ISpatialExtent, Iterable, IGeometricShape,
        NetworkSerializable, NetworkDeserializable {

    ShapeValue                shape          = null;
    Grid                      grid           = null;
    ReferencedEnvelope        envelope       = null;
    CoordinateReferenceSystem crs            = null;
    VectorCoverage            features       = null;
    double                    gridResolution = -1.0;
    ISpatialIndex             index          = null;
    int                       extentType     = INCONSISTENT;

    // the four states this can be in
    /**
     * Extent has only been set with info that require a merge before we can establish
     * what the usable extent will be.
     */
    public static final int   INCONSISTENT   = -1;

    /**
     * extent represents a shape location (may be single, multiple or a point) of
     * multiplicity 1.
     */
    public static final int   SINGLE_SHAPE   = 0;

    /**
     * Extent represents more than one shape, with one state per shape.
     */
    public static final int   MULTIPLE_SHAPE = 1;

    /**
     * Extent represents a grid, possibly with a shape that doesn't cover it entirely.
     */
    public static final int   GRID           = 2;

    class Tessellation implements ITessellation {

        @Override
        public Iterator iterator() {
            // TODO return a shape iterator built upon the _features field.
            return null;
        }

    }

    /*
     * cloning constructor
     */
    private SpaceExtent(SpaceExtent extent) {
        shape = extent.shape;
        grid = extent.grid;
        envelope = extent.envelope;
        crs = extent.crs;
        features = extent.features;
        extentType = extent.extentType;
    }

    // @Override
    public BitSet getMask() {
        return grid == null ? null : ((RasterActivationLayer) (grid.activationLayer));
    }

    /**
     * Return the world in lat/lon. TODO add one with a grid parameter in m.
     * 
     * @return the world
     */
    public static SpaceExtent WORLD() {
        return new SpaceExtent(ShapeValue.WORLD());
    }

    public SpaceExtent(ShapeValue shape) {
        this.shape = shape;
        crs = shape.getCRS();
        envelope = shape.getEnvelope();
        extentType = SINGLE_SHAPE;
    }

    public SpaceExtent(Grid grid) {
        this.grid = grid;
        shape = grid.getShape();
        envelope = grid.getEnvelope();
        extentType = GRID;
        crs = grid.crs;
    }

    public SpaceExtent(ShapeValue shape, int x, int y) throws KlabException {
        // TODO no activation layer
        this.grid = new Grid(shape, x, y, true);
        this.shape = shape;
        envelope = shape.getEnvelope();
        extentType = GRID;
    }

    public SpaceExtent(VectorCoverage vector) {
        features = vector;
        extentType = MULTIPLE_SHAPE;
    }

    public SpaceExtent() {
        extentType = INCONSISTENT;
    }

    public SpaceExtent(double resolution) {
        gridResolution = resolution;
        extentType = INCONSISTENT;
        // TODO review - this is a forcing.
    }

    
    
    public SpaceExtent(IGeometricShape shape, IGrid grid) throws KlabException {
        this.crs = Geospace.getCRSFromID("EPSG:" + shape.getSRID());
        this.shape = new ShapeValue(shape.getGeometry(), crs);
        if (grid != null) {
            this.grid = new Grid(this.shape, grid.getXCells(), grid.getYCells());
            if (grid instanceof Grid) {
               this.grid.offsetInSupergrid = ((Grid)grid).offsetInSupergrid;
               this.grid.superGridId = ((Grid)grid).superGridId;
            }
            this.envelope = ((Grid) grid).getEnvelope();
        } else {
            this.envelope = this.shape.getEnvelope();
        }
    }

    @Override
    public IExtent merge(IExtent extent, boolean force) throws KlabException {

        if (extent instanceof Space && force) {
            SpaceExtent ret = new SpaceExtent(this);
            if (!((Space) extent).isForcing()) {
                throw new KlabUnsupportedOperationException("cannot merge non-forcing foreign spatial extent in SpatialExtent");
            }
            ret.grid = new Grid(getShape(), Grid.parseResolution(((Space) extent).getForcingDefinition()));
            return ret;
        }

        if (!(extent instanceof SpaceExtent)) {
            throw new KlabValidationException("space extent cannot merge non-space extent");
        }

        SpaceExtent ret = new SpaceExtent(this);
        SpaceExtent oth = (SpaceExtent) extent;

        /*
         * TODO figure out mandatory vs. not. These are all false, which probably
         * shouldn't be - either pass to merge or be smarter.
         */
        if (oth.grid != null) {
            ret.set(oth.grid, force);
        } else if (oth.features != null) {
            ret.set(oth.features, oth.shape, force);
        } else if (oth.shape != null) {
            ret.set(oth.shape, force);
        } else if (oth.gridResolution > 0.0) {
            ret.setGridResolution(oth.gridResolution, force);
        }

        return ret;
    }

    /*
     * constructor & merger w/ multiple shapes + optional boundary. If mandatory, we HAVE
     * to have these, and incompatible previous specs are an error.
     */
    public void set(VectorCoverage vector, ShapeValue shape, boolean mandatory)
            throws KlabException {

        if (extentType == INCONSISTENT) {

            if (gridResolution > 0.0) {

                /*
                 * make grid; subset to union of shapes
                 */

            } else {
                features = vector;
                extentType = MULTIPLE_SHAPE;
            }
        } else if (extentType == GRID) {

            /*
             * TODO error if mandatory, else activate the grid
             */
        }

        if (shape != null) {

            /*
             * intersect existing shape if any
             */
            if (this.shape != null) {
                this.shape = this.shape.intersection(shape);
            } else {
                this.shape = shape;
            }

        }
    }

    /*
     * constructor & merger w/ grid + optional boundary. If mandatory, we HAVE to have
     * these, and incompatible previous specs are an error.
     */
    public void set(Grid grid, boolean mandatory) throws KlabException {

        if (extentType == INCONSISTENT) {
            this.grid = grid;
        } else if (!mandatory) {

            throw new KlabValidationException("conflicting spatial extent merge: grid -> "
                    + getTypeLabel());

        } else {

            /*
             * TODO - we want to force a grid.
             */
        }
    }

    private String getTypeLabel() {

        switch (extentType) {
        case INCONSISTENT:
            return "inconsistent";
        case GRID:
            return "grid";
        case SINGLE_SHAPE:
            return "single shape";
        case MULTIPLE_SHAPE:
            return "multiple shape";
        }
        return null;
    }

    /*
     * constructor & merger w/ single shape. If mandatory, we HAVE to have these, and
     * incompatible previous specs are an error.
     */
    public void set(ShapeValue shape, boolean mandatory) throws KlabException {

        /*
         * TODO lots to do here - particularly, if we force a new shape on a grid, must
         * recompute multiplicity etc. The new shape may be larger if this is called by
         * union() (which does not happen at the moment, but intersection() can).
         */

        if (extentType == INCONSISTENT) {

            this.shape = shape;
            if (gridResolution > 0.0) {
                grid = new Grid(shape, gridResolution);
                extentType = GRID;
            }

        } else if (extentType == GRID) {

            /*
             * mandatory? subset the grid : complain
             */
            if (mandatory) {
                grid.createActivationLayer(shape);
            } else {
                throw new KlabValidationException("conflicting spatial extent merge: shape -> grid");
            }

        } else if (extentType == SINGLE_SHAPE) {

            /*
             * if mandatory intersect shapes; if not, complain
             */
            if (mandatory) {
                this.shape = shape.intersection(shape);
            } else {
                throw new KlabValidationException("conflicting spatial extent merge: shape -> shape");
            }

        } else if (extentType == MULTIPLE_SHAPE) {

            /*
             * filter the shapes that intersect the given one and set them to the
             * intersection.
             */
            features = intersectFeatures(features, shape);
        }
    }

    private VectorCoverage intersectFeatures(VectorCoverage _features2, ShapeValue shape) {
        throw new KlabRuntimeException("unsupported shape intersection");
    }

    /*
     * Set the grid resolution and become a grid if we have a boundary. If mandatory, we
     * HAVE to have this, and incompatible previous specs are an error.
     */
    public void setGridResolution(double res, boolean mandatory) throws KlabException {

        gridResolution = res;

        /*
         * adopt, adapt and improve
         */
        if (extentType == GRID) {

            /*
             * resample if mandatory, complain otherwise
             */
        } else if (extentType == SINGLE_SHAPE) {

            /*
             * make grid
             */
            grid = new Grid(shape, gridResolution);
            extentType = GRID;

        } else if (extentType == MULTIPLE_SHAPE) {

            /*
             * make grid with union
             */
        }

    }

    @Override
    public boolean isConsistent() {
        return extentType != INCONSISTENT && !getShape().isEmpty() && getShape().isValid();
    }

    @Override
    public Type getGeometryType() {
        return getShape().getGeometryType();
    }

    @Override
    public long getValueCount() {
        return getMultiplicity();
    }

    @Override
    public boolean isSpatiallyDistributed() {
        return getValueCount() > 1;
    }

    @Override
    public boolean isTemporallyDistributed() {
        return false;
    }

    @Override
    public IObserver getObserver() {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public long getMultiplicity() {

        if (grid != null) {
            return grid.getCellCount();
        }

        if (features != null) {
            // TODO
        }

        // TODO the rest

        return 1;
    }

    @Override
    public IExtent intersection(IExtent other) throws KlabException {

        if (!(other instanceof SpaceExtent)) {
            throw new KlabValidationException("non-spatial extent being intersected with a spatial one");
        }

        SpaceExtent oth = (SpaceExtent) other;
        ShapeValue mys = getShape();
        ShapeValue its = oth.getShape();

        if (mys == null && its == null) {
            return new SpaceExtent();
        } else if (mys == null && its != null) {
            return new SpaceExtent(its);
        } else if (mys != null && its == null) {
            return new SpaceExtent(mys);
        }

        return new SpaceExtent(mys.intersection(its));
    }

    @Override
    public IExtent union(IExtent other) throws KlabException {

        if (!(other instanceof SpaceExtent)) {
            throw new KlabValidationException("non-spatial extent being intersected with a spatial one");
        }

        SpaceExtent oth = (SpaceExtent) other;
        ShapeValue mys = getShape();
        ShapeValue its = oth.getShape();

        if (mys == null && its == null) {
            return new SpaceExtent();
        } else if (mys == null && its != null) {
            return new SpaceExtent(its);
        } else if (mys != null && its == null) {
            return new SpaceExtent(mys);
        }

        return new SpaceExtent(mys.union(its));
    }

    @Override
    public boolean contains(IExtent o) throws KlabException {
        SpaceExtent e = (SpaceExtent) o;
        return shape.contains(e.shape);
    }

    @Override
    public boolean overlaps(IExtent o) throws KlabException {
        SpaceExtent e = (SpaceExtent) o;
        return shape.overlaps(e.shape);
    }

    @Override
    public boolean intersects(IExtent o) throws KlabException {
        SpaceExtent e = (SpaceExtent) o;
        return shape.intersects(e.shape);
    }

    @Override
    public IConcept getDomainConcept() {
        return KLAB.c(NS.SPACE_DOMAIN);
    }

    @Override
    public IExtent collapse() {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public ISpatialExtent getExtent(int stateIndex) {

        if (grid != null) {
            return new SpaceExtent(grid.getCellPolygon(stateIndex));
        }

        // TODO return n-th shape if vector coverage != null

        // TODO return self if index = 0 && it's a single shape.

        return null;
    }

    @Override
    public boolean isCovered(int stateIndex) {
        return grid == null || grid.isCovered(stateIndex);
    }

    @Override
    public Object getValue(int index) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public Iterator iterator() {
        // TODO Auto-generated method stub
        return null;
    }

    public boolean isGrid() {
        return grid != null;
    }

    @Override
    public Grid getGrid() {
        return grid;
    }

    @Override
    public ShapeValue getShape() {
        return shape;
    }

    public ReferencedEnvelope getEnvelope() {
        return envelope;
    }

    @Override
    public boolean isTemporal() {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public boolean isSpatial() {
        // TODO Auto-generated method stub
        return true;
    }

    @Override
    public ISpatialExtent getSpace() {
        return this;
    }

    @Override
    public ITemporalExtent getTime() {
        return null;
    }

    public CoordinateReferenceSystem getCRS() {
        return crs;
    }

    @Override
    public Pair, Double> checkCoverage(ITopologicallyComparable obj)
            throws KlabException {

        if (this.shape == null) {
            throw new KlabInternalErrorException("checking coverage on an indefinite spatial extent");
        }

        ShapeValue other = null;
        if (obj instanceof SpaceExtent) {
            other = ((SpaceExtent) obj).getShape();
        } else if (obj instanceof ShapeValue) {
            other = (ShapeValue) obj;
        }

        if (other == null) {
            throw new KlabInternalErrorException("checking spatial coverage of a non-spatial object");
        }

        ShapeValue common = this.shape.intersection(other);
        double prop = common.getGeometry().getArea() / this.shape.getGeometry().getArea();

        return new Pair<>(common, prop);
    }

    @Override
    public ITopologicallyComparable union(ITopologicallyComparable obj) throws KlabException {

        SpaceExtent ret = new SpaceExtent(this);

        if (this.shape == null) {
            return ret;
        }

        ShapeValue other = null;
        if (obj instanceof SpaceExtent) {
            other = ((SpaceExtent) obj).getShape();
        } else if (obj instanceof ShapeValue) {
            other = (ShapeValue) obj;
        }

        if (other == null) {
            return new SpaceExtent();
        }

        ShapeValue common = this.shape.union(other);

        ret.set(common, true);

        return ret;
    }

    @Override
    public ITopologicallyComparable intersection(ITopologicallyComparable obj)
            throws KlabException {

        SpaceExtent ret = new SpaceExtent(this);

        if (this.shape == null) {
            return ret;
        }

        ShapeValue other = null;
        if (obj instanceof SpaceExtent) {
            other = ((SpaceExtent) obj).getShape();
        } else if (obj instanceof ShapeValue) {
            other = (ShapeValue) obj;
        }

        if (other == null) {
            return new SpaceExtent();
        }

        ShapeValue common = this.shape.intersection(other);

        return new SpaceExtent(common);
    }

    @Override
    public double getCoveredExtent() {
        return shape == null ? 0 : shape.getArea();
    }
    
    @Override
    public String toString() {
        return "S[" + envelope + "]";
    }

    @Override
    public boolean isEmpty() {
        return shape == null || shape.getGeometry().isEmpty();
    }

    @Override
    public double getMinX() {
        return envelope.getMinX();
    }

    @Override
    public double getMinY() {
        return envelope.getMinY();
    }

    @Override
    public double getMaxX() {
        return envelope.getMaxX();
    }

    @Override
    public double getMaxY() {
        return envelope.getMaxY();
    }

    @Override
    public IScale getScale() {

        // TODO won't be called, but it should return the scale we're part of
        return null;
    }

    // @Override
    // public Object adapt() {
    //
    // Map ret = new HashMap();
    //
    // ret.put("multiplicity", getValueCount());
    // ret.put("domain", getDomainConcept().toString());
    //
    // ret.put("minx", getEnvelope().getMinX());
    // ret.put("miny", getEnvelope().getMinY());
    // ret.put("maxx", getEnvelope().getMaxX());
    // ret.put("maxy", getEnvelope().getMaxY());
    //
    // if (_grid != null) {
    // ret.put("grid", _grid.adapt());
    // }
    // ShapeValue shape = getShape();
    // if (shape != null) {
    // ret.put("shape", shape.toString());
    // }
    // ret.put("crs", Geospace.getCRSIdentifier(_crs, true));
    // return ret;
    // }

    @Override
    public int[] getDimensionSizes() {

        if (features != null) {
            // TODO number of features return new int[] {)
        } else if (grid != null) {
            return new int[] { grid.getXCells(), grid.getYCells() };
        }
        return new int[] { 1 };
    }

    @Override
    public int[] getDimensionOffsets(int linearOffset, boolean rowFirst) {

        if (features != null) {
            return new int[] { linearOffset };
        } else if (grid != null) {
            if (rowFirst) {
                int[] xy = grid.getXYOffsets(linearOffset);
                return new int[] { xy[1], xy[0] };
            }
            return grid.getXYOffsets(linearOffset);
        }
        return new int[] { 0 };
    }

    @Override
    public ISpatialExtent getExtent() {
        return shape == null ? null : shape.asExtent();
    }

    @Override
    public String getCRSCode() {
        return Geospace.getCRSIdentifier(crs, false);
    }

    @Override
    public ITessellation getTessellation() {
        return new Tessellation();
    }

    @Override
    public IStorage getStorage() {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public Iterator iterator(Index index) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public IMetadata getMetadata() {
        // TODO Auto-generated method stub
        return null;
    }

    //
    // @Override
    // public IConcept getDirectType() {
    // // TODO Auto-generated method stub
    // return null;
    // }
    //
    // @Override
    // public INamespace getNamespace() {
    // // TODO Auto-generated method stub
    // return null;
    // }
    //
    // @Override
    // public boolean is(Object other) {
    // // TODO Auto-generated method stub
    // return false;
    // }

    @Override
    public int locate(Locator locator) {
        if (locator instanceof SpaceLocator) {
            if (locator.isAll())
                return GENERIC_LOCATOR;
            if (grid != null) {
                if (((SpaceLocator) locator).isLatLon()) {
                    return getGrid()
                            .getOffsetFromWorldCoordinates(((SpaceLocator) locator).lon, ((SpaceLocator) locator).lat);
                } else {
                    return getGrid().getOffset(((SpaceLocator) locator).x, ((SpaceLocator) locator).y);
                }
            }
        }
        return INAPPROPRIATE_LOCATOR;
    }

    @Override
    public Geometry getStandardizedGeometry() {
        return shape.getStandardizedGeometry();
    }

    @Override
    public Geometry getGeometry() {
        return shape.getGeometry();
    }

    public static IExtent sanitize(ISpatialExtent e) throws KlabException {
        if (e instanceof SpaceExtent) {
            return e;
        }
        SpaceExtent ret = null;
        String crsId = e.getCRSCode();
        ShapeValue shape = new ShapeValue(((IGeometricShape) e).getGeometry(), Geospace.getCRSFromID(crsId));
        if (e.getGrid() != null) {
            Grid grid = new Grid(shape, e.getGrid().getXCells(), e.getGrid().getYCells());
            ret = new SpaceExtent(grid);
        } else {
            ret = new SpaceExtent(shape);
        }
        return ret;
    }

    @Override
    public String asText() {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public int getSRID() {
        return Integer.parseInt(Path.getLast(Geospace.getCRSIdentifier(crs, true), ':'));
    }

    @Override
    public Mediator getMediator(IExtent extent, IObservableSemantics observable, IConcept trait) {
        if (getGrid() != null && ((ISpatialExtent) extent).getGrid() == null
                && ((ISpatialExtent) extent).getMultiplicity() == 1) {
            return new GridToShape(observable, this, ShapeValue
                    .sanitize(((ISpatialExtent) extent).getShape()).asExtent(), trait);
        }
        if (getGrid() == null && ((ISpatialExtent) extent).getGrid() != null
                && getMultiplicity() == 1) {
            return new ShapeToGrid(observable, ShapeValue
                    .sanitize(((ISpatialExtent) extent).getShape()).asExtent(), this);
        }
        if (getGrid() != null && ((ISpatialExtent) extent).getGrid() != null) {
            return new GridToGrid(observable, this, extent, trait);
        }
        if (getGrid() == null && ((ISpatialExtent) extent).getGrid() == null) {
            return new ShapeToShape(observable, this, ShapeValue
                    .sanitize(((ISpatialExtent) extent).getShape()).asExtent());
        }
        return null;
    }

    @Override
    public double getArea() {
        return shape.getArea();
    }

    @Override
    public ISpatialIndex getIndex(boolean makeNew) {

        if (makeNew) {
            return KLAB.MFACTORY.getSpatialIndex(this);
        }

        if (this.index == null) {
            this.index = KLAB.MFACTORY.getSpatialIndex(this);
        }
        return this.index;

    }

    @Override
    public boolean isConstant() {
        return getMultiplicity() == 1;
    }

    @Override
    public void deserialize(IModelBean object) {

        if (!(object instanceof org.integratedmodelling.common.beans.Space)) {
            throw new KlabInternalRuntimeException("cannot adapt a "
                    + object.getClass().getCanonicalName() + " to a spatial extent");
        }
        org.integratedmodelling.common.beans.Space bean = (org.integratedmodelling.common.beans.Space) object;

        extentType = SINGLE_SHAPE;
        this.crs = Geospace.getCRSFromID(bean.getCrs());
        this.envelope = new ReferencedEnvelope(bean.getMinX(), bean.getMaxX(), bean.getMinY(), bean
                .getMaxY(), this.crs);
        if (bean.getShape() != null) {
            try {
                this.shape = new ShapeValue(bean.getShape());
            } catch (KlabValidationException e) {
                throw new KlabRuntimeException(e);
            }
        }

        if (bean.getGrid() != null) {
            extentType = GRID;
            this.grid = new Grid(crs, bean.getGrid().getMinX(), bean.getGrid().getMinY(), bean.getGrid()
                    .getMaxX(), bean.getGrid().getMaxY(), bean
                            .getGrid().getXDivs(), bean.getGrid().getYDivs());

            if (this.shape != null) {
                grid.shape = this.shape;
            } else {
                this.envelope = grid.getEnvelope();
                this.shape = new ShapeValue(this.envelope);
            }
        }
    }

    @SuppressWarnings("unchecked")
    @Override
    public  T serialize(Class desiredClass) {

        if (!desiredClass.isAssignableFrom(org.integratedmodelling.common.beans.Space.class)) {
            throw new KlabInternalRuntimeException("cannot adapt a space extent to "
                    + desiredClass.getCanonicalName());
        }

        org.integratedmodelling.common.beans.Space ret = new org.integratedmodelling.common.beans.Space();

        ret.setMinX(getMinX());
        ret.setMinY(getMinY());
        ret.setMaxX(getMaxX());
        ret.setMaxY(getMaxY());
        ret.setCrs(getCRSCode());
        ret.setMultiplicity(getMultiplicity());

        if (getShape() != null) {
            ret.setShape("EPSG:4326 " + getStandardizedGeometry().toString());
        }

        if (grid != null) {
            org.integratedmodelling.common.beans.Grid grd = new org.integratedmodelling.common.beans.Grid();
            grd.setMinX(grid.getMinX());
            grd.setMinY(grid.getMinY());
            grd.setMaxX(grid.getMaxX());
            grd.setMaxY(grid.getMaxY());
            grd.setXDivs(grid.getXCells());
            grd.setYDivs(grid.getYCells());
            if (getShape() != null) {
                grd.setShape("EPSG:4326 " + getStandardizedGeometry().toString());
            }
            ret.setGrid(grd);
        }
        return (T) ret;
    }

    @Override
    public boolean isDynamic() {
        return false;
    }

    /**
     * Builds a 1-cell grid from a non-gridded extent. Does not set it in the extent
     * (i.e., {@link #getGrid()} will keep returning null after this is called).
     * 
     * @return
     */
    public Grid makeGrid() {
        try {
            return new Grid(getShape(), 1, 1);
        } catch (KlabException e) {
            throw new KlabRuntimeException(e);
        }
    }

    @Override
    public void addChangeListener(ChangeListener listener) {
        // TODO Auto-generated method stub

    }

    @Override
    public Class getGeometryClass() {
        return getGeometry() == null ? null : getGeometry().getClass();
    }

    
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy