/* * Geotoolkit.org - An Open Source Java GIS Toolkit * http://www.geotoolkit.org * * (C) 2014, Geomatys * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License. * * This library 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 GNU * Lesser General Public License for more details. */ package org.geotoolkit.processing.coverage.mathcalc; import org.apache.sis.storage.DataStoreException; import org.geotoolkit.storage.coverage.CoverageReference; import org.geotoolkit.storage.coverage.PyramidalCoverageReference; import org.geotoolkit.coverage.grid.GeneralGridGeometry; import org.geotoolkit.coverage.io.GridCoverageReader; import org.geotoolkit.cql.CQL; import org.geotoolkit.cql.CQLException; import org.geotoolkit.factory.FactoryFinder; import org.geotoolkit.filter.WrapFilterFactory2; import static org.geotoolkit.parameter.Parameters.value; import org.geotoolkit.utility.parameter.ParametersExt; import org.geotoolkit.processing.AbstractProcess; import org.geotoolkit.process.ProcessException; import org.opengis.coverage.Coverage; import org.opengis.filter.FilterFactory2; import org.opengis.filter.expression.Expression; import org.opengis.filter.expression.Function; import org.opengis.parameter.ParameterValueGroup; import org.opengis.referencing.crs.CoordinateReferenceSystem; import org.opengis.referencing.operation.TransformException; import org.opengis.util.FactoryException; import org.apache.sis.util.Utilities; /** * * @author Johann Sorel (Geomatys) */ public class MathCalcProcess extends AbstractProcess { public MathCalcProcess(Coverage[] inCoverages, String inFormula, String[] inMapping, CoverageReference outCoverage){ this(toParameters(inCoverages, inFormula, inMapping, outCoverage)); } public MathCalcProcess(ParameterValueGroup params) { super(MathCalcDescriptor.INSTANCE, params); } private static ParameterValueGroup toParameters(Coverage[] inCoverages, String inFormula, String[] inMapping, CoverageReference outCoverage){ final ParameterValueGroup params = MathCalcDescriptor.INSTANCE.getInputDescriptor().createValue(); ParametersExt.getOrCreateValue(params, "inCoverages").setValue(inCoverages); ParametersExt.getOrCreateValue(params, "inFormula").setValue(inFormula); ParametersExt.getOrCreateValue(params, "inMapping").setValue(inMapping); ParametersExt.getOrCreateValue(params, "inResultCoverage").setValue(outCoverage); return params; } @Override protected void execute() throws ProcessException { final Coverage[] inCoverages = value(MathCalcDescriptor.IN_COVERAGES, inputParameters); final String inFormula = value(MathCalcDescriptor.IN_FORMULA, inputParameters); final String[] inMapping = value(MathCalcDescriptor.IN_MAPPING, inputParameters); final CoverageReference outRef = value(MathCalcDescriptor.IN_RESULT_COVERAGE, inputParameters); final GeneralGridGeometry gg; final GridCoverageReader outReader; try { outReader = outRef.acquireReader(); gg = outReader.getGridGeometry(outRef.getImageIndex()); outRef.recycle(outReader); } catch (DataStoreException ex) { throw new ProcessException(ex.getMessage(), this, ex); } //create expression final FilterFactory2 ff = new ExtFilterFactory(); final Expression exp; try { exp = CQL.parseExpression(inFormula, ff); } catch (CQLException ex) { throw new ProcessException(ex.getMessage(), this, ex); } // prepare dynamic pick object final MathCalcCoverageEvaluator evaluator; try { evaluator = new MathCalcCoverageEvaluator(inCoverages,inMapping,exp,gg.getCoordinateReferenceSystem()); } catch (FactoryException ex) { throw new ProcessException(ex.getMessage(), this, ex); } final FillCoverage filler = new FillCoverage(); try { if(outRef instanceof PyramidalCoverageReference){ filler.fill((PyramidalCoverageReference)outRef, evaluator); }else{ filler.fill(outRef, evaluator, null); } } catch (DataStoreException ex) { throw new ProcessException(ex.getMessage(), this, ex); } catch (TransformException ex) { throw new ProcessException(ex.getMessage(), this, ex); } catch (FactoryException ex) { throw new ProcessException(ex.getMessage(), this, ex); } } //TODO, for later, handle offsets on axis with syntax U(x,y+10,z) and U(gx-20,gy,gz) private static class ExtFilterFactory extends WrapFilterFactory2{ public ExtFilterFactory() { super((FilterFactory2)FactoryFinder.getFilterFactory(null)); } @Override public Function function(String name, Expression... args) { return super.function(name, args); } } /** * Find common crs which can be used for mathcalc process. * * @param crss * @return * @throws IllegalArgumentException */ public static CoordinateReferenceSystem findCommunCrs(CoordinateReferenceSystem ... crss) throws IllegalArgumentException{ CoordinateReferenceSystem result = null; for(CoordinateReferenceSystem crs : crss){ if(result==null){ result = crs; }else{ final int nbr = result.getCoordinateSystem().getDimension(); final int nbc = crs.getCoordinateSystem().getDimension(); if (nbr==nbc && Utilities.equalsIgnoreMetadata(nbr, nbc)) { //same number of dimensions and equal, OK }else{ throw new IllegalArgumentException("CRS have different number of dimensions"); } } } return result; } }