org.integratedmodelling.engine.geospace.gis.GISOperations 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.gis;
import java.awt.image.RenderedImage;
import java.util.Iterator;
import java.util.function.Function;
import javax.media.jai.iterator.RandomIter;
import javax.media.jai.iterator.RandomIterFactory;
import org.geotools.coverage.grid.GridCoverage2D;
import org.integratedmodelling.api.modelling.IActiveDirectObservation;
import org.integratedmodelling.api.modelling.IDirectObservation;
import org.integratedmodelling.api.modelling.IObservableSemantics;
import org.integratedmodelling.api.modelling.IScale;
import org.integratedmodelling.api.modelling.IScale.Index;
import org.integratedmodelling.api.modelling.IState;
import org.integratedmodelling.api.modelling.ISubject;
import org.integratedmodelling.api.monitoring.IMonitor;
import org.integratedmodelling.api.runtime.IContext;
import org.integratedmodelling.api.runtime.ISession;
import org.integratedmodelling.api.runtime.ITask;
import org.integratedmodelling.api.runtime.ITask.Status;
import org.integratedmodelling.common.configuration.KLAB;
import org.integratedmodelling.common.space.SpaceLocator;
import org.integratedmodelling.common.states.State;
import org.integratedmodelling.common.states.States;
import org.integratedmodelling.common.time.TimeLocator;
import org.integratedmodelling.common.vocabulary.NS;
import org.integratedmodelling.engine.geospace.coverage.raster.RasterCoverage;
import org.integratedmodelling.engine.geospace.extents.Grid;
import org.integratedmodelling.engine.geospace.extents.SpaceExtent;
import org.integratedmodelling.exceptions.KlabException;
import org.integratedmodelling.exceptions.KlabUnsupportedOperationException;
import org.integratedmodelling.exceptions.KlabValidationException;
import org.jgrasstools.gears.libs.monitor.IJGTProgressMonitor;
import es.unex.sextante.core.ITaskMonitor;
import es.unex.sextante.dataObjects.IRasterLayer;
import es.unex.sextante.geotools.GTRasterLayer;
public class GISOperations {
public final static String INFO_CLASS = "GIS_PROCESS";
private static final double BASIN_IMPORTANCE_THRESHOLD = 0.05;
private static final int WATERSHEDS_TO_EXTRACT = 1;
public static class TaskMonitor implements IMonitor, ITaskMonitor, IJGTProgressMonitor {
IMonitor _monitor;
private String _name;
public TaskMonitor(IMonitor monitor) {
_monitor = monitor;
}
@Override
public boolean isCanceled() {
return _monitor.getTask().getStatus() == Status.INTERRUPTED;
}
// JGT methods
@Override
public void beginTask(String name, int totalWork) {
_name = name;
// _monitor.defineProgressSteps(totalWork);
// _monitor.info("beginning " + name, INFO_CLASS);
}
@Override
public void message(String message) {
// _monitor.info(message, INFO_CLASS);
}
@Override
public void errorMessage(String message) {
_monitor.error(message);
}
@Override
public void done() {
// _monitor.info("finished " + _name, INFO_CLASS);
}
@Override
public void internalWorked(double work) {
// TODO Auto-generated method stub
}
@Override
public void setCanceled(boolean value) {
if (value) {
// _monitor.stop(null);
}
}
@Override
public void setTaskName(String name) {
_name = name;
}
@Override
public void subTask(String name) {
}
@Override
public void worked(int work) {
// _monitor.addProgress(work, "");
}
@Override
public T adapt(Class adaptee) {
// TODO Auto-generated method stub
return null;
}
@Override
public void exceptionThrown(String message) {
_monitor.error(message);
}
@Override
public void onModuleExit() {
// TODO Auto-generated method stub
}
@Override
public void info(Object info, String infoClass) {
// TODO Auto-generated method stub
}
@Override
public void warn(Object o) {
// TODO Auto-generated method stub
}
@Override
public void error(Object o) {
// TODO Auto-generated method stub
}
@Override
public void debug(Object o) {
// TODO Auto-generated method stub
}
@Override
public ITask getTask() {
// TODO Auto-generated method stub
return null;
}
@Override
public ISession getSession() {
// TODO Auto-generated method stub
return null;
}
@Override
public void close() {
// TODO Auto-generated method stub
}
@Override
public void setDescriptionPrefix(String arg0) {
// TODO Auto-generated method stub
}
@Override
public void setDeterminate(boolean arg0) {
// TODO Auto-generated method stub
}
@Override
public void setProcessDescription(String arg0) {
// TODO Auto-generated method stub
}
@Override
public void setProgress(int arg0) {
// TODO Auto-generated method stub
}
@Override
public void setProgress(int arg0, int arg1) {
// TODO Auto-generated method stub
}
@Override
public void setProgressText(String arg0) {
// TODO Auto-generated method stub
}
@Override
public boolean hasErrors() {
// TODO Auto-generated method stub
return false;
}
@Override
public IContext getContext() {
// TODO Auto-generated method stub
return null;
}
@Override
public void send(Object o) {
// TODO Auto-generated method stub
}
}
public static IRasterLayer stateToRaster(IState state) throws KlabException {
GTRasterLayer ret = null;
RasterCoverage coverage = new RasterCoverage(state);
ret = new GTRasterLayer();
ret.create(coverage.getCoverage());
return ret;
}
/**
* Turn a Thinklab state into a Geotools GridCoverage2D.
*
* @param state
* @return coverage
* @throws KlabException
*/
public static GridCoverage2D stateToCoverage(IState state) throws KlabException {
RasterCoverage coverage = new RasterCoverage(state);
return coverage.getCoverage();
}
/**
* Turn a Thinklab state into a Geotools GridCoverage2D.
*
* @param state
* @return coverage
* @throws KlabException
*/
public static GridCoverage2D stateToCoverage(IState state, Iterable locators)
throws KlabException {
RasterCoverage coverage = new RasterCoverage(state, locators);
return coverage.getCoverage();
}
/**
* Aggregate a dynamic k.LAB state into a Geotools GridCoverage2D.
*
* @param state
* @return coverage
* @throws KlabException
*/
public static GridCoverage2D aggregateStateToCoverage(IState state)
throws KlabException {
if (!(state.getScale().isSpatiallyDistributed() && state.getScale().isSpatiallyDistributed())) {
throw new KlabUnsupportedOperationException("wrong call: cannot aggregate a non-temporal spatial state with this call");
}
int tslices = (int)state.getScale().getTime().getMultiplicity() /* FIXME as usual */ - 3;
double[] buffer = new double[(int)state.getScale().getSpace().getMultiplicity()];
for (int i = 0; i < tslices; i++) {
Index index = state.getScale().getIndex(TimeLocator.get(i), SpaceLocator.all());
int so = 0;
for (Iterator it = state.iterator(index); it.hasNext();) {
Object vs = it.next();
if (vs == null) {
vs = Double.NaN;
}
if (vs instanceof Number) {
if (Double.isNaN(((Number)vs).doubleValue()) || Double.isNaN(buffer[so])) {
buffer[so] = Double.NaN;
} else {
buffer[so] +=((Number)vs).doubleValue();
}
}
so++;
}
}
/*
* average unless this is an accumulating stock
*/
if (!state.getObservable().getSemantics().is(KLAB.c(NS.CORE_EXTENSIVE_PHYSICAL_PROPERTY))) {
for (int i = 0; i < buffer.length; i++) {
buffer[i] /= tslices;
}
}
return new RasterCoverage("aggregated", (Grid) state.getSpace().getGrid(), buffer).getCoverage();
}
public static IState rasterToState(IRasterLayer layer, IObservableSemantics observable, ISubject context)
throws KlabException {
GTRasterLayer l = (GTRasterLayer) layer;
SpaceExtent ext = (SpaceExtent) context.getScale().getSpace();
if (ext.getGrid() == null) {
throw new KlabValidationException("cannot return a raster layer from a non-grid extent");
}
Grid grid = ext.getGrid();
double[] data = new double[grid.getCellCount()];
for (int i = 0; i < grid.getCellCount(); i++) {
int[] xy = grid.getXYOffsets(i);
data[i] = l.getCellValueAsDouble(xy[0], xy[1]);
}
// FIXME see what to do with dynamic state - depends on semantics
return new State(data, observable, context, false, false);
}
public static int countNodata(GridCoverage2D layer, IDirectObservation context) throws KlabException {
SpaceExtent ext = (SpaceExtent) context.getScale().getSpace();
if (ext.getGrid() == null) {
throw new KlabValidationException("cannot return a raster layer from a non-grid extent");
}
Grid grid = ext.getGrid();
RenderedImage image = layer.getRenderedImage();
RandomIter itera = RandomIterFactory.create(image, null);
int nodata = 0;
for (int i = 0; i < grid.getCellCount(); i++) {
int[] xy = grid.getXYOffsets(i);
double d = itera.getSampleDouble(xy[0], xy[1], 0);
if (Double.isNaN(d)) {
nodata ++;
}
}
return nodata;
}
/**
* Get a static state built from the passed layer.
*
* @param layer
* @param observable
* @param context
* @param label
* @return state
* @throws KlabException
*/
public static IState coverageToState(GridCoverage2D layer, IObservableSemantics observable, IActiveDirectObservation context, String label)
throws KlabException {
return coverageToState(layer, observable, context, label, null);
}
/**
* Get a static state built from the passed layer. Do not add to a context.
*
* @param layer
* @param observable
* @param context
* @param label
* @return state
* @throws KlabException
*/
public static IState coverageToState(GridCoverage2D layer, IObservableSemantics observable, IContext context, String label, Function transformation )
throws KlabException {
SpaceExtent ext = (SpaceExtent) context.getSubject().getScale().getSpace();
if (ext.getGrid() == null) {
throw new KlabValidationException("cannot return a raster layer from a non-grid extent");
}
Grid grid = ext.getGrid();
RenderedImage image = layer.getRenderedImage();
RandomIter itera = RandomIterFactory.create(image, null);
IState ret = States.createStatic(observable, context.getSubject().getScale(), context);
for (int i = 0; i < grid.getCellCount(); i++) {
int[] xy = grid.getXYOffsets(i);
double value = itera.getSampleDouble(xy[0], xy[1], 0);
States.set(ret, transformation == null ? value : transformation.apply(value), i);
}
ret.getMetadata().put(NS.DISPLAY_LABEL_PROPERTY, label);
return ret;
}
/**
* Get a static state built from the passed layer.
*
* @param layer
* @param observable
* @param context
* @param label
* @return state
* @throws KlabException
*/
public static IState coverageToState(GridCoverage2D layer, IObservableSemantics observable, IActiveDirectObservation context, String label, Function transformation )
throws KlabException {
SpaceExtent ext = (SpaceExtent) context.getScale().getSpace();
if (ext.getGrid() == null) {
throw new KlabValidationException("cannot return a raster layer from a non-grid extent");
}
Grid grid = ext.getGrid();
RenderedImage image = layer.getRenderedImage();
RandomIter itera = RandomIterFactory.create(image, null);
IState ret = context.getStaticState(observable);
for (int i = 0; i < grid.getCellCount(); i++) {
int[] xy = grid.getXYOffsets(i);
double value = itera.getSampleDouble(xy[0], xy[1], 0);
States.set(ret, transformation == null ? value : transformation.apply(value), i);
}
ret.getMetadata().put(NS.DISPLAY_LABEL_PROPERTY, label);
return ret;
}
}