/* * This file is part of JGrasstools (http://www.jgrasstools.org) * (C) HydroloGIS - www.hydrologis.com * * JGrasstools is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) 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 * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.jgrasstools.hortonmachine.modules.hydrogeomorphology.lwrecruitment; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.TreeMap; import oms3.annotations.Author; import oms3.annotations.Description; import oms3.annotations.Execute; import oms3.annotations.In; import oms3.annotations.Keywords; import oms3.annotations.Label; import oms3.annotations.License; import oms3.annotations.Name; import oms3.annotations.Out; import oms3.annotations.Status; import org.geotools.coverage.grid.GridCoverage2D; import org.geotools.data.simple.SimpleFeatureCollection; import org.geotools.feature.DefaultFeatureCollection; import org.jgrasstools.gears.io.rasterreader.OmsRasterReader; import org.jgrasstools.gears.io.rasterwriter.OmsRasterWriter; import org.jgrasstools.gears.io.vectorreader.OmsVectorReader; import org.jgrasstools.gears.io.vectorwriter.OmsVectorWriter; import org.jgrasstools.gears.libs.modules.JGTConstants; import org.jgrasstools.gears.libs.modules.JGTModel; import org.jgrasstools.gears.utils.features.FeatureExtender; import org.jgrasstools.gears.utils.features.FeatureUtilities; import org.jgrasstools.hortonmachine.modules.network.PfafstetterNumber; import org.jgrasstools.hortonmachine.modules.network.networkattributes.NetworkChannel; import org.opengis.feature.simple.SimpleFeature; @Description(OmsLW11_NetworkPropagator.DESCRIPTION) @Author(name = OmsLW11_NetworkPropagator.AUTHORS, contact = OmsLW11_NetworkPropagator.CONTACTS) @Label(OmsLW11_NetworkPropagator.LABEL) @Keywords(OmsLW11_NetworkPropagator.KEYWORDS) @Name("_" + OmsLW11_NetworkPropagator.NAME) @Status(OmsLW11_NetworkPropagator.STATUS) @License(OmsLW11_NetworkPropagator.LICENSE) public class OmsLW11_NetworkPropagator extends JGTModel implements LWFields { @Description(inNetPoints_DESCR) @In public SimpleFeatureCollection inNetPoints = null; @Description(ratioLogsLengthChannelWidthHillslope_DESCR) @In public double pRatioLogsLengthChannelWidthHillslope = 0.8; @Description(ratioLogsLengthChannelWidthChannel_DESCR) @In public double pRatioLogsLengthChannelWidthChannel = 1.0; @Description(ratioLogsDiameterWaterDepth_DESCR) @In public double pRatioLogsDiameterWaterDepth = 0.8; @Description(outNetPoints_DESCR) @Out public SimpleFeatureCollection outNetPoints = null; // VARS DOC START public static final String outNetPoints_DESCR = "The output network points layer with the critical sections labelled in the attribute table."; public static final String inNetPoints_DESCR = "The input network points layer with the additional attributes vegetation height and timber volume."; public static final String ratioLogsLengthChannelWidthHillslope_DESCR = "The ratio between the lenght of the logs and the maximum channel width for the vegetation coming from the hillslopes (vegetation characteristics of the current section)."; public static final String ratioLogsLengthChannelWidthChannel_DESCR = "The ratio between the lenght of the logs and the maximum channel width for the vegetation coming from upstream (vegetation characteristics from upstream not blocked)."; public static final String ratioLogsDiameterWaterDepth_DESCR = "The ratio between the diameter of the logs and the water depth corresponding to maximum channel widht."; public static final int STATUS = Status.EXPERIMENTAL; public static final String LICENSE = "General Public License Version 3 (GPLv3)"; public static final String NAME = "lw11_networkpropagator"; public static final String LABEL = JGTConstants.HYDROGEOMORPHOLOGY + "/LWRecruitment"; public static final String KEYWORDS = "critical, wood"; public static final String CONTACTS = "http://www.hydrologis.com"; public static final String AUTHORS = "Silvia Franceschi, Andrea Antonello"; public static final String DESCRIPTION = "Label the critical section for the transit of the wood and calculate the cumulated volume of biomass in each blocking section."; // VARS DOC END /* * specify the names of the attributes fields */ private final String FIELD_LINKID = LINKID; private final String FIELD_DBH = VEG_DBH; @Execute public void process() throws Exception { /* * store the network points in a collection and map the Pfafstetter codes together with * the features ID in an hashmap. */ List<SimpleFeature> networkFeatures = FeatureUtilities.featureCollectionToList(inNetPoints); List<PfafstetterNumber> pfafstetterNumberList = new ArrayList<PfafstetterNumber>(); HashMap<String, TreeMap<Integer, SimpleFeature>> pfafstetterNumber2FeaturesMap = new HashMap<String, TreeMap<Integer, SimpleFeature>>(); // TODO add the check if the DBH field is available or not for the check on diameter!! for( SimpleFeature networkFeature : networkFeatures ) { Object pfaffObject = networkFeature.getAttribute(NetworkChannel.PFAFNAME); if (pfaffObject instanceof String) { String pfaffString = (String) pfaffObject; PfafstetterNumber pfaf = new PfafstetterNumber(pfaffString); if (!pfafstetterNumberList.contains(pfaf)) { pfafstetterNumberList.add(pfaf); } TreeMap<Integer, SimpleFeature> featureTreeMap = pfafstetterNumber2FeaturesMap.get(pfaffString); if (featureTreeMap == null) { featureTreeMap = new TreeMap<Integer, SimpleFeature>(); pfafstetterNumber2FeaturesMap.put(pfaffString, featureTreeMap); } Object linkidObj = networkFeature.getAttribute(FIELD_LINKID); if (linkidObj instanceof Integer) { Integer linkId = (Integer) linkidObj; featureTreeMap.put(linkId, networkFeature); } } } // sort the list of Pfafstetter to be ready to navigate the network Collections.sort(pfafstetterNumberList); /* * prepare the output feature collection as an extention of the input with 3 * additional attributes for critical sections */ FeatureExtender ext = null; DefaultFeatureCollection outputFC = new DefaultFeatureCollection(); /* * consider each link and navigate downstream each */ double maxUpstreamHeight = -1; double maxUpstreamDiameter = -1; // create the variables to use in the cycle List<PfafstetterNumber> lastUpStreamPfafstetters = new ArrayList<PfafstetterNumber>(); List<Double> lastUpStreamMaxHeights = new ArrayList<Double>(); List<Double> lastUpStreamMaxDiameters = new ArrayList<Double>(); List<String> lastUpStreamCriticSourceForLength = new ArrayList<String>(); List<String> lastUpStreamCriticSourceForDiameter = new ArrayList<String>(); /* * start the main cycle with the elaborations to identify the critical sections */ pm.beginTask("Processing network...", pfafstetterNumberList.size()); for( PfafstetterNumber pfafstetterNumber : pfafstetterNumberList ) { TreeMap<Integer, SimpleFeature> featuresMap = pfafstetterNumber2FeaturesMap.get(pfafstetterNumber.toString()); String criticSourceForHeigth = null; String criticSourceForDiameter = null; for( int i = 0; i < lastUpStreamPfafstetters.size(); i++ ) { PfafstetterNumber lastUpStreamPfafstetter = lastUpStreamPfafstetters.get(i); if (pfafstetterNumber.isDownStreamOf(lastUpStreamPfafstetter)) { /* * if the other is directly upstream, check its max height and label * the critical section */ double lastUpstreamHeight = lastUpStreamMaxHeights.get(i); double lastUpstreamDiameter = lastUpStreamMaxDiameters.get(i); if (lastUpstreamHeight > maxUpstreamHeight) { maxUpstreamHeight = lastUpstreamHeight; criticSourceForHeigth = lastUpStreamCriticSourceForLength.get(i); } if (lastUpstreamDiameter > maxUpstreamDiameter) { maxUpstreamDiameter = lastUpstreamDiameter; criticSourceForDiameter = lastUpStreamCriticSourceForDiameter.get(i); } } } for( SimpleFeature feature : featuresMap.values() ) { String linkid = feature.getAttribute(FIELD_LINKID).toString(); double width = (Double) feature.getAttribute(WIDTH2); double height = (Double) feature.getAttribute(VEG_H); Object diameterObj = feature.getAttribute(VEG_DBH); double diameter; if (diameterObj instanceof Double) { diameter = (Double) diameterObj; } else { diameter = -1; } Object waterDepthObj = feature.getAttribute(FIELD_WATER_LEVEL2); double waterDepth; if (waterDepthObj instanceof Double) { waterDepth = (Double) waterDepthObj; } else { waterDepth = -1; } if (ext ==null) { if (diameter<0) { ext = new FeatureExtender(inNetPoints.getSchema(), new String[]{FIELD_ISCRITIC_LOCAL_FOR_HEIGHT, FIELD_ISCRITIC_GLOBAL_FOR_HEIGHT, FIELD_CRITIC_SOURCE_FOR_HEIGHT}, new Class[]{Integer.class, Integer.class, String.class}); }else{ ext = new FeatureExtender(inNetPoints.getSchema(), new String[]{FIELD_ISCRITIC_LOCAL_FOR_HEIGHT, FIELD_ISCRITIC_GLOBAL_FOR_HEIGHT, FIELD_CRITIC_SOURCE_FOR_HEIGHT, FIELD_ISCRITIC_LOCAL_FOR_DIAMETER, FIELD_ISCRITIC_GLOBAL_FOR_DIAMETER, FIELD_CRITIC_SOURCE_FOR_DIAMETER}, new Class[]{Integer.class, Integer.class, String.class, Integer.class, Integer.class, String.class}); } } if (height > maxUpstreamHeight) { maxUpstreamHeight = height; criticSourceForHeigth = pfafstetterNumber + "-" + linkid; } /* * label the critical sections */ // critical from local parameters veg_h > width int isCriticLocalForLogHeight = 0; int isCriticGlobalForLogHeight = 0; if (height / width > pRatioLogsLengthChannelWidthHillslope) { isCriticLocalForLogHeight = 1; } // critical on vegetation coming from upstream if (maxUpstreamHeight / width > pRatioLogsLengthChannelWidthChannel) { isCriticGlobalForLogHeight = 1; maxUpstreamHeight = -1; } // update the field with the origin of critical sections if (criticSourceForHeigth == null) criticSourceForHeigth = ""; String tmpCriticSourceForHeight = criticSourceForHeigth; if (isCriticGlobalForLogHeight == 0) { tmpCriticSourceForHeight = ""; } /* * check on the ratio between the diameter of the logs and the channel depth will be * done only if the dbh field in the input net points layer is available */ if (diameter > 0.0) { if (diameter > maxUpstreamDiameter) { maxUpstreamDiameter = diameter; criticSourceForDiameter = pfafstetterNumber + "-" + linkid; } int isCriticLocalForLogDiameter = 0; int isCriticGlobalForLogDiameter = 0; // critical from local parameters veg_d > waterdepth if (diameter / waterDepth > pRatioLogsDiameterWaterDepth) { isCriticLocalForLogDiameter = 1; } // critical on vegetation coming from upstream if (maxUpstreamDiameter / waterDepth > pRatioLogsDiameterWaterDepth) { isCriticGlobalForLogDiameter = 1; maxUpstreamDiameter = -1; } if (criticSourceForDiameter == null) criticSourceForDiameter = ""; String tmpCriticSourceForDiameter = criticSourceForDiameter; if (isCriticGlobalForLogDiameter == 0) { tmpCriticSourceForDiameter = ""; } SimpleFeature newFeature = ext .extendFeature(feature, new Object[]{isCriticLocalForLogHeight, isCriticGlobalForLogHeight, tmpCriticSourceForHeight, isCriticLocalForLogDiameter, isCriticGlobalForLogDiameter, tmpCriticSourceForDiameter}); outputFC.add(newFeature); lastUpStreamMaxDiameters.add(maxUpstreamDiameter); lastUpStreamCriticSourceForDiameter.add(criticSourceForDiameter); } else { // no other checks will be done for critical sections SimpleFeature newFeature = ext.extendFeature(feature, new Object[]{isCriticLocalForLogHeight, isCriticGlobalForLogHeight, tmpCriticSourceForHeight}); outputFC.add(newFeature); } } // add the point to the list for the next step lastUpStreamPfafstetters.add(pfafstetterNumber); lastUpStreamMaxHeights.add(maxUpstreamHeight); lastUpStreamCriticSourceForLength.add(criticSourceForHeigth); pm.worked(1); } pm.done(); outNetPoints = outputFC; } public static void main( String[] args ) throws Exception { String base = "D:/lavori_tmp/unibz/2016_06_gsoc/data01/"; OmsLW11_NetworkPropagator ex = new OmsLW11_NetworkPropagator(); ex.inNetPoints = OmsVectorReader .readVector(base + "net_point_width_damsbridg_slope_lateral_inund_veg_80_rast_lateral3_nodbh.shp"); ex.pRatioLogsDiameterWaterDepth = 0.7; ex.pRatioLogsLengthChannelWidthChannel = 0.8; ex.pRatioLogsLengthChannelWidthHillslope = 0.9; ex.process(); SimpleFeatureCollection outNetPoints = ex.outNetPoints; OmsVectorWriter.writeVector(base + "net_point_width_damsbridg_slope_lateral_inund_veg_80_rast_lateral3_crit_nodbh.shp", outNetPoints); } }