/* * 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.riversections; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.TreeMap; import java.util.Map.Entry; import org.geotools.data.simple.SimpleFeatureCollection; import org.geotools.feature.DefaultFeatureCollection; import org.geotools.feature.simple.SimpleFeatureBuilder; import org.geotools.feature.simple.SimpleFeatureTypeBuilder; import org.jgrasstools.gears.libs.exceptions.ModelsRuntimeException; import org.jgrasstools.gears.utils.geometry.GeometryUtilities; import org.jgrasstools.hortonmachine.modules.hydrogeomorphology.lwrecruitment.LWFields; import org.opengis.feature.simple.SimpleFeature; import org.opengis.feature.simple.SimpleFeatureType; import org.opengis.referencing.crs.CoordinateReferenceSystem; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.GeometryFactory; import com.vividsolutions.jts.geom.LineString; import com.vividsolutions.jts.geom.Point; /** * Abstract class for river extractors. * * @author Andrea Antonello (www.hydrologis.com) * @author Silvia Franceschi (www.hydrologis.com) */ public abstract class ARiverSectionsExtractor { public static final String FIELD_SECTIONPOINT_ELEV = "elev"; public static final String FIELD_ELEVATION = "elev"; public static final String FIELD_SECTIONPOINT_INDEX = "index"; public static final String FIELD_SECTION_ID = "sectionid"; public static final String FIELD_PROGRESSIVE = "prog"; protected int pointsWithSectionsNum; protected GeometryFactory gf = GeometryUtilities.gf(); protected List<RiverPoint> riverPointsList; protected CoordinateReferenceSystem crs; protected SimpleFeatureCollection sectionsCollection; protected SimpleFeatureCollection sectionPointsCollection; protected SimpleFeatureCollection riverPointsCollection; public List<RiverPoint> getOrderedNetworkPoints() { return riverPointsList; } public int getSectionsNum() { return pointsWithSectionsNum; } public SimpleFeatureCollection getSectionsCollection() { if (sectionsCollection == null) createSectionsCollections(); return sectionsCollection; } public SimpleFeatureCollection getSectionPointsCollection() { if (sectionPointsCollection == null) createSectionsCollections(); return sectionPointsCollection; } public SimpleFeatureCollection getRiverPointsCollection() { if (riverPointsCollection == null) createSectionsCollections(); return riverPointsCollection; } protected void createSectionsCollections() { SimpleFeatureTypeBuilder sectionTypeBuilder = new SimpleFeatureTypeBuilder(); sectionTypeBuilder.setName("sectionlines"); sectionTypeBuilder.setCRS(crs); sectionTypeBuilder.add("the_geom", LineString.class); sectionTypeBuilder.add(FIELD_SECTION_ID, Integer.class); sectionTypeBuilder.add(FIELD_PROGRESSIVE, Double.class); sectionTypeBuilder.add(LWFields.GAUKLER, Double.class); SimpleFeatureType sectionType = sectionTypeBuilder.buildFeatureType(); SimpleFeatureBuilder sectionBuilder = new SimpleFeatureBuilder(sectionType); SimpleFeatureTypeBuilder riverPointsTypeBuilder = new SimpleFeatureTypeBuilder(); riverPointsTypeBuilder.setName("riverpoints"); riverPointsTypeBuilder.setCRS(crs); riverPointsTypeBuilder.add("the_geom", Point.class); riverPointsTypeBuilder.add(FIELD_SECTION_ID, Integer.class); riverPointsTypeBuilder.add(FIELD_PROGRESSIVE, Double.class); riverPointsTypeBuilder.add(FIELD_ELEVATION, Double.class); SimpleFeatureType riverType = riverPointsTypeBuilder.buildFeatureType(); SimpleFeatureBuilder riverBuilder = new SimpleFeatureBuilder(riverType); SimpleFeatureTypeBuilder sectionPointsTypeBuilder = new SimpleFeatureTypeBuilder(); sectionPointsTypeBuilder.setName("sectionpoint"); sectionPointsTypeBuilder.setCRS(crs); sectionPointsTypeBuilder.add("the_geom", Point.class); sectionPointsTypeBuilder.add(FIELD_SECTIONPOINT_INDEX, Integer.class); sectionPointsTypeBuilder.add(FIELD_SECTIONPOINT_ELEV, Double.class); sectionPointsTypeBuilder.add(FIELD_PROGRESSIVE, Double.class); sectionPointsTypeBuilder.add(FIELD_SECTION_ID, Integer.class); SimpleFeatureType sectionPointsType = sectionPointsTypeBuilder.buildFeatureType(); SimpleFeatureBuilder sectionPointsBuilder = new SimpleFeatureBuilder(sectionPointsType); sectionsCollection = new DefaultFeatureCollection(); sectionPointsCollection = new DefaultFeatureCollection(); riverPointsCollection = new DefaultFeatureCollection(); int index = 0; for( RiverPoint netPoint : riverPointsList ) { int sectionId = netPoint.getSectionId(); if (sectionId == -1) { sectionId = index; } if (netPoint.hasSection) { LineString sectionGeometry = netPoint.sectionGeometry; Coordinate[] sectionCoordinates = sectionGeometry.getCoordinates(); LineString simpleSectionGeometry = gf.createLineString( new Coordinate[]{sectionCoordinates[0], sectionCoordinates[sectionCoordinates.length - 1]}); Object[] sectionValues = new Object[]{simpleSectionGeometry, sectionId, netPoint.progressiveDistance, netPoint.getSectionGauklerStrickler()}; sectionBuilder.addAll(sectionValues); SimpleFeature sectionFeature = sectionBuilder.buildFeature(null); ((DefaultFeatureCollection) sectionsCollection).add(sectionFeature); Coordinate[] coordinates = sectionGeometry.getCoordinates(); List<Double> sectionProgressive = netPoint.getSectionProgressive(); for( int i = 0; i < coordinates.length; i++ ) { Point point = gf.createPoint(coordinates[i]); Object[] sectionPointsValues = new Object[]{point, i, coordinates[i].z, sectionProgressive.get(i), sectionId}; sectionPointsBuilder.addAll(sectionPointsValues); SimpleFeature sectionPointsFeature = sectionPointsBuilder.buildFeature(null); ((DefaultFeatureCollection) sectionPointsCollection).add(sectionPointsFeature); } } else { // if there is no section, a single point is placed double progressiveDistance = netPoint.progressiveDistance; Coordinate coord = netPoint.point; Point point = gf.createPoint(coord); Object[] riverPointValues = new Object[]{point, sectionId, progressiveDistance, coord.z}; riverBuilder.addAll(riverPointValues); SimpleFeature riverFeature = riverBuilder.buildFeature(null); ((DefaultFeatureCollection) riverPointsCollection).add(riverFeature); } index++; } } /** * Get the river info as produced by the {@link OmsRiverSectionsExtractor}. * * @param riverPointsFeatures the river points. * @param sectionFeatures the extracted sections. * @param sectionPointsFeatures the section points. * @return the {@link RiverInfo}. */ public static RiverInfo getRiverInfo( List<SimpleFeature> riverPointsFeatures, List<SimpleFeature> sectionFeatures, List<SimpleFeature> sectionPointsFeatures ) { RiverInfo riverInfo = new RiverInfo(); for( SimpleFeature riverPointFeature : riverPointsFeatures ) { int sectionId = ((Number) riverPointFeature.getAttribute(ARiverSectionsExtractor.FIELD_SECTION_ID)).intValue(); riverInfo.orderedRiverPoints.put(sectionId, riverPointFeature); } int count = 0; riverInfo.riverCoords = new Coordinate[riverInfo.orderedRiverPoints.size()]; for( Entry<Integer, SimpleFeature> riverEntry : riverInfo.orderedRiverPoints.entrySet() ) { SimpleFeature riverPoint = riverEntry.getValue(); Coordinate coordinate = ((Geometry) riverPoint.getDefaultGeometry()).getCoordinate(); double elev = ((Number) riverPoint.getAttribute(ARiverSectionsExtractor.FIELD_ELEVATION)).doubleValue(); riverInfo.riverCoords[count++] = new Coordinate(coordinate.x, coordinate.y, elev); } GeometryFactory gf = new GeometryFactory(); LineString riverGeometry = gf.createLineString(riverInfo.riverCoords); for( SimpleFeature sectionFeature : sectionFeatures ) { int sectionId = ((Number) sectionFeature.getAttribute(ARiverSectionsExtractor.FIELD_SECTION_ID)).intValue(); riverInfo.orderedSections.put(sectionId, sectionFeature); } HashMap<Integer, TreeMap<Integer, SimpleFeature>> sectionId2PointId2PointMap = new HashMap<>(); for( SimpleFeature pointFeature : sectionPointsFeatures ) { int sectionId = ((Number) pointFeature.getAttribute(ARiverSectionsExtractor.FIELD_SECTION_ID)).intValue(); TreeMap<Integer, SimpleFeature> pointId2PointMap = sectionId2PointId2PointMap.get(sectionId); if (pointId2PointMap == null) { pointId2PointMap = new TreeMap<>(); sectionId2PointId2PointMap.put(sectionId, pointId2PointMap); } int pointId = ((Number) pointFeature.getAttribute(ARiverSectionsExtractor.FIELD_SECTIONPOINT_INDEX)).intValue(); pointId2PointMap.put(pointId, pointFeature); } for( Entry<Integer, SimpleFeature> sectionEntry : riverInfo.orderedSections.entrySet() ) { Integer sectionId = sectionEntry.getKey(); SimpleFeature sectionFeature = sectionEntry.getValue(); double progressive = ((Number) sectionFeature.getAttribute(ARiverSectionsExtractor.FIELD_PROGRESSIVE)).doubleValue(); Object attribute = sectionFeature.getAttribute(LWFields.GAUKLER); if (attribute == null) { throw new ModelsRuntimeException("The input section data do not have the value of KS.", "ARiverSectionsExtractor"); } double ks = ((Number) attribute).doubleValue(); Geometry sectionLine = (Geometry) sectionFeature.getDefaultGeometry(); Geometry intersectionPoint = riverGeometry.intersection(sectionLine); if (intersectionPoint == null) { throw new ModelsRuntimeException("All sections have to intersect the river line.", "ARiverSectionsExtractor#getRiverInfo"); } TreeMap<Integer, SimpleFeature> sectionPoints = sectionId2PointId2PointMap.get(sectionId); Coordinate[] sectionCoords = new Coordinate[sectionPoints.size()]; count = 0; for( Entry<Integer, SimpleFeature> pointEntry : sectionPoints.entrySet() ) { SimpleFeature sectionPoint = pointEntry.getValue(); sectionCoords[count++] = ((Geometry) sectionPoint.getDefaultGeometry()).getCoordinate(); } LineString sectionLineWithPoints = gf.createLineString(sectionCoords); RiverPoint rp = new RiverPoint(intersectionPoint.getCoordinate(), progressive, sectionLineWithPoints, ks); rp.setSectionId(sectionId); riverInfo.orderedNetworkPoints.add(rp); } riverInfo.extractedSectionsCount = riverInfo.orderedNetworkPoints.size(); for( Entry<Integer, SimpleFeature> riverEntry : riverInfo.orderedRiverPoints.entrySet() ) { SimpleFeature riverPoint = riverEntry.getValue(); Coordinate coordinate = ((Geometry) riverPoint.getDefaultGeometry()).getCoordinate(); double progressive = ((Number) riverPoint.getAttribute(ARiverSectionsExtractor.FIELD_PROGRESSIVE)).doubleValue(); RiverPoint rp = new RiverPoint(coordinate, progressive, null, null); rp.setSectionId(riverEntry.getKey()); riverInfo.orderedNetworkPoints.add(rp); } Collections.sort(riverInfo.orderedNetworkPoints); return riverInfo; } public static List<RiverPoint> riverInfo2RiverPoints( RiverInfo riverInfo ) { List<RiverPoint> sectionPoints = new ArrayList<RiverPoint>(); int orderedNetworkPointsSize = riverInfo.orderedNetworkPoints.size(); for( int i = 0; i < orderedNetworkPointsSize; i++ ) { RiverPoint currentNetworkPoint = riverInfo.orderedNetworkPoints.get(i); if (currentNetworkPoint.hasSection) { sectionPoints.add(currentNetworkPoint); } } return sectionPoints; } }