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