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

org.integratedmodelling.engine.modelling.runtime.mediators.MediationOperations 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.modelling.runtime.mediators;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

import org.integratedmodelling.api.modelling.INumericObserver;
import org.integratedmodelling.api.modelling.IObservableSemantics;
import org.integratedmodelling.api.modelling.IScale.Locator;
import org.integratedmodelling.api.modelling.IState;
import org.integratedmodelling.api.modelling.IState.Mediator;
import org.integratedmodelling.api.modelling.IState.Mediator.Aggregation;
import org.integratedmodelling.api.space.IGrid;
import org.integratedmodelling.api.space.IGrid.Cell;
import org.integratedmodelling.collections.Pair;
import org.integratedmodelling.common.configuration.KLAB;
import org.integratedmodelling.common.space.IGeometricShape;
import org.integratedmodelling.common.vocabulary.NS;
import org.integratedmodelling.engine.geospace.extents.Grid;
import org.integratedmodelling.engine.geospace.literals.ShapeValue;
import org.integratedmodelling.exceptions.KlabException;

import com.vividsolutions.jts.geom.Envelope;

public class MediationOperations {

    public static class Subgrid implements IGrid {

        Grid grid;
        int  xofs = 0;
        int  yofs = 0;

        private Subgrid(Grid grid, int xofs, int yofs) {
            this.grid = grid;
            this.xofs = xofs;
            this.yofs = yofs;
        }

        public int getOriginalX(int x) {
            return x + xofs;
        }

        public int getOriginalY(int y) {
            return y + yofs;
        }

        @Override
        public int getYCells() {
            return grid.getYCells();
        }

        @Override
        public int getXCells() {
            return grid.getXCells();
        }

        @Override
        public int getCellCount() {
            return grid.getCellCount();
        }

        @Override
        public int getOffset(int x, int y) {
            return grid.getOffset(x, y);
        }

        @Override
        public boolean isActive(int x, int y) {
            return grid.isActive(x, y);
        }

        @Override
        public int getOffsetFromWorldCoordinates(double lon, double lat) {
            return grid.getOffsetFromWorldCoordinates(lon, lat);
        }

        @Override
        public int[] getXYOffsets(int index) {
            return grid.getXYOffsets(index);
        }

        @Override
        public double[] getCoordinates(int index) {
            return grid.getCoordinates(index);
        }

        @Override
        public Locator getLocator(int x, int y) {
            return grid.getLocator(x, y);
        }

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

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

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

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

        @Override
        public double getCellWidth() {
            return grid.getCellWidth();
        }

        @Override
        public double getCellHeight() {
            return grid.getCellHeight();
        }

        @Override
        public Iterator iterator() {
            return grid.iterator();
        }

        public Cell getOriginalCell(Cell cell) {
            return grid.getCell(cell.getX() + xofs, cell.getY() + yofs);
        }

        @Override
        public double getCellArea() {
            return grid.getCellArea();
        }
    }

    public static Subgrid getSubgrid(IGrid grid, IGeometricShape shape) throws KlabException {

        Envelope genv = new Envelope(grid.getMinX(), grid.getMaxX(), grid.getMinY(), grid.getMaxY());
        Envelope senv = shape.getGeometry().getEnvelope().getEnvelopeInternal();

        if (!genv.covers(senv)) {
            return null;
        }

        /*
         * adjusts envelope boundaries to cover original cells exactly
         */
        double gxmin = senv.getMinX();
        double gxmax = senv.getMaxX();
        double dx = gxmax - gxmin;
        double gymin = senv.getMinY();
        double gymax = senv.getMaxY();
        double dy = gymax - gymin;

        int nx = (int) (dx / grid.getCellWidth());
        int ny = (int) (dy / grid.getCellHeight());

        if ((nx * grid.getCellWidth()) < dx) {
            nx++;
            gxmin -= (grid.getCellWidth() / 2);
            gxmax += (grid.getCellWidth() / 2);
        }
        if ((ny * grid.getCellHeight()) < dy) {
            ny++;
            gymin -= (grid.getCellHeight() / 2);
            gymax += (grid.getCellHeight() / 2);
        }

        int xofs = (int) ((gxmin - grid.getMinX()) / grid.getCellWidth());
        int yofs = (int) ((gymin - grid.getMinY()) / grid.getCellHeight());

        return new Subgrid(new Grid((ShapeValue) shape, nx, ny), xofs, yofs);
    }

    /**
     * Return all cells from the ORIGINAL grid that cover the shape, with the corresponding coverage.
     * 
     * @param grid
     * @param shape
     * @param useSimpleIntersection if true, just check for containment and return full coverage. Much faster. Use when
     *        no weighted aggregation is necessary.
     * @return covered cells
     * @throws KlabException
     */
    public static Iterable> getCoveredCells(IGrid grid, IGeometricShape shape, boolean useSimpleIntersection)
            throws KlabException {

        ShapeValue sshape = ShapeValue.sanitize(shape);
        Subgrid subgrid = getSubgrid(grid, sshape);
        if (subgrid == null) {
            return null;
        }

        Collection> ret = new ArrayList<>();
        for (Cell cell : subgrid) {
            double d = sshape.getCoverage(cell, useSimpleIntersection);
            if (d > 0) {
                ret.add(new Pair(subgrid.getOriginalCell(cell), d));
            }
        }

        return ret;
    }

    public static IState.Mediator.Aggregation getAggregator(IObservableSemantics observable) {

        IState.Mediator.Aggregation ret = Mediator.Aggregation.MAJORITY;
        if (observable.getObserver() instanceof INumericObserver) {
            ret = Aggregation.AVERAGE;
            if (observable.is(KLAB.c(NS.CORE_EXTENSIVE_PHYSICAL_PROPERTY))) {
                ret = Aggregation.SUM;
            }
        }
        return ret;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy