All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jgrasstools.gears.utils.features.FeatureUtilities Maven / Gradle / Ivy

/*
 * JGrass - Free Open Source Java GIS http://www.jgrass.org 
 * (C) HydroloGIS - www.hydrologis.com 
 * 
 * This library is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Library General Public License as published by the Free
 * Software Foundation; either version 2 of the License, or (at your option) any
 * later version.
 * 
 * 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 Library General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU Library General Public License
 * along with this library; if not, write to the Free Foundation, Inc., 59
 * Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */
package org.jgrasstools.gears.utils.features;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.geotools.data.DataUtilities;
import org.geotools.data.DefaultTransaction;
import org.geotools.data.FeatureStore;
import org.geotools.data.Transaction;
import org.geotools.data.shapefile.ShapefileDataStore;
import org.geotools.data.shapefile.ShapefileDataStoreFactory;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.data.simple.SimpleFeatureIterator;
import org.geotools.data.simple.SimpleFeatureSource;
import org.geotools.feature.FeatureCollection;
import org.geotools.feature.FeatureCollections;
import org.geotools.feature.simple.SimpleFeatureBuilder;
import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
import org.geotools.gce.grassraster.JGrassConstants;
import org.geotools.geometry.Envelope2D;
import org.jgrasstools.gears.libs.monitor.IJGTProgressMonitor;
import org.jgrasstools.gears.utils.geometry.GeometryUtilities;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.feature.type.AttributeDescriptor;
import org.opengis.referencing.crs.CoordinateReferenceSystem;

import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.CoordinateList;
import com.vividsolutions.jts.geom.Envelope;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.LinearRing;
import com.vividsolutions.jts.geom.Point;
import com.vividsolutions.jts.geom.Polygon;

public class FeatureUtilities {

    /**
     * Order the geometries of a list to be all directed in the same direction
     * 
     * @param geometryList the list of geometries to be ordered
     * @param thresHold a scalar value that defines the max distance between two points to be the
     *        same
     * @return a list of ordered coordinates
     */
    @SuppressWarnings("unchecked")
    public static CoordinateList orderLineGeometries( List geometryList, double thresHold ) {
        /*
         * first search the feature that is one of the two external points
         */
        Geometry firstFeature = null;
        boolean foundFirst = true;
        boolean foundSecond = true;
        for( Geometry feature : geometryList ) {
            foundFirst = true;
            foundSecond = true;

            Coordinate[] coords = feature.getCoordinates();

            Coordinate first = coords[0];
            Coordinate last = coords[coords.length - 1];

            for( Geometry compareFeature : geometryList ) {
                if (compareFeature.equals(feature))
                    continue;
                Coordinate[] compareCoords = compareFeature.getCoordinates();

                Coordinate comparefirst = compareCoords[0];
                Coordinate comparelast = compareCoords[compareCoords.length - 1];

                /*
                 * check if the next point is far away
                 */
                if (first.distance(comparefirst) < thresHold || first.distance(comparelast) < thresHold) {
                    foundFirst = false;
                }
                if (last.distance(comparefirst) < thresHold || last.distance(comparelast) < thresHold) {
                    foundSecond = false;
                }

            }
            if (foundFirst || foundSecond) {
                firstFeature = feature;
                break;
            }

        }
        if (firstFeature == null) {
            throw new RuntimeException();
        }
        CoordinateList coordinateList = new CoordinateList();
        Coordinate[] coords = firstFeature.getCoordinates();
        if (foundSecond) {
            for( int i = 0; i < coords.length; i++ ) {
                coordinateList.add(coords[coords.length - i - 1]);
            }
        } else {
            for( int i = 0; i < coords.length; i++ ) {
                coordinateList.add(coords[i]);
            }
        }

        // if (foundFirst) {
        // addCoordsInProperDirection(foundFirst, coordinateList, coords, true,
        // 0);
        // }else{
        // addCoordsInProperDirection(foundSecond, coordinateList, coords, true,
        // 0);
        // }

        geometryList.remove(firstFeature);

        Coordinate currentCoordinate = coordinateList.getCoordinate(coordinateList.size() - 1);
        while( geometryList.size() != 0 ) {

            for( int j = 0; j < geometryList.size(); j++ ) {
                System.out.println(j);
                Geometry compareGeom = geometryList.get(j);
                Coordinate[] compareCoords = compareGeom.getCoordinates();

                Coordinate comparefirst = compareCoords[0];
                Coordinate comparelast = compareCoords[compareCoords.length - 1];

                // System.out.println(j + " "
                // + currentCoordinate.distance(comparefirst) + " "
                // + currentCoordinate.distance(comparelast));

                /*
                 * check if the next point is far away
                 */
                if (currentCoordinate.distance(comparefirst) < thresHold) {
                    for( int i = 0; i < compareCoords.length; i++ ) {
                        coordinateList.add(compareCoords[i]);
                    }
                    currentCoordinate = new Coordinate(comparelast);
                    geometryList.remove(compareGeom);
                    break;
                } else if (currentCoordinate.distance(comparelast) < thresHold) {
                    for( int i = 0; i < compareCoords.length; i++ ) {
                        coordinateList.add(compareCoords[compareCoords.length - i - 1]);
                    }
                    currentCoordinate = new Coordinate(comparefirst);
                    geometryList.remove(compareGeom);
                    break;
                }

            }

        }

        return coordinateList;
    }

    /**
     * Create a featurecollection from a vector of features
     * 
     * @param features - the vectore of features
     * @return the created featurecollection
     */
    public static SimpleFeatureCollection createFeatureCollection( SimpleFeature... features ) {
        SimpleFeatureCollection fcollection = FeatureCollections.newCollection();

        for( SimpleFeature feature : features ) {
            fcollection.add(feature);
        }
        return fcollection;
    }

    /**
     * 

* Convert a csv file to a FeatureCollection. * This for now supports only point geometries.
* For different crs it also performs coor transformation. *

*

* NOTE: this doesn't support date attributes *

* * @param csvFile the csv file. * @param crs the crs to use. * @param fieldsAndTypes the {@link Map} of filed names and {@link JGrassConstants#CSVTYPESARRAY types}. * @param pm progress monitor. * @param separatorthe separator to use, if null, comma is used. * @return the created {@link FeatureCollection} * @throws Exception */ @SuppressWarnings("nls") public static SimpleFeatureCollection csvFileToFeatureCollection( File csvFile, CoordinateReferenceSystem crs, LinkedHashMap fieldsAndTypesIndex, String separator, IJGTProgressMonitor pm ) throws Exception { GeometryFactory gf = new GeometryFactory(); Map> typesMap = JGrassConstants.CSVTYPESCLASSESMAP; String[] typesArray = JGrassConstants.CSVTYPESARRAY; if (separator == null) { separator = ","; } SimpleFeatureTypeBuilder b = new SimpleFeatureTypeBuilder(); b.setName("csvimport"); b.setCRS(crs); b.add("the_geom", Point.class); int xIndex = -1; int yIndex = -1; Set fieldNames = fieldsAndTypesIndex.keySet(); String[] fieldNamesArray = (String[]) fieldNames.toArray(new String[fieldNames.size()]); for( int i = 0; i < fieldNamesArray.length; i++ ) { String fieldName = fieldNamesArray[i]; Integer typeIndex = fieldsAndTypesIndex.get(fieldName); if (typeIndex == 0) { xIndex = i; } else if (typeIndex == 1) { yIndex = i; } else { Class class1 = typesMap.get(typesArray[typeIndex]); b.add(fieldName, class1); } } SimpleFeatureType featureType = b.buildFeatureType(); SimpleFeatureCollection newCollection = FeatureCollections.newCollection(); Collection orderedTypeIndexes = fieldsAndTypesIndex.values(); Integer[] orderedTypeIndexesArray = (Integer[]) orderedTypeIndexes.toArray(new Integer[orderedTypeIndexes.size()]); BufferedReader bR = new BufferedReader(new FileReader(csvFile)); String line = null; int featureId = 0; pm.beginTask("Importing raw data", -1); while( (line = bR.readLine()) != null ) { pm.worked(1); if (line.startsWith("#")) { continue; } SimpleFeatureBuilder builder = new SimpleFeatureBuilder(featureType); Object[] values = new Object[fieldNames.size() - 1]; String[] lineSplit = line.split(separator); double x = Double.parseDouble(lineSplit[xIndex]); double y = Double.parseDouble(lineSplit[yIndex]); Point point = gf.createPoint(new Coordinate(x, y)); values[0] = point; int objIndex = 1; for( int i = 0; i < lineSplit.length; i++ ) { if (i == xIndex || i == yIndex) { continue; } String value = lineSplit[i]; int typeIndex = orderedTypeIndexesArray[i]; String typeName = typesArray[typeIndex]; if (typeName.equals(typesArray[3])) { values[objIndex] = value; } else if (typeName.equals(typesArray[4])) { values[objIndex] = new Double(value); } else if (typeName.equals(typesArray[5])) { values[objIndex] = new Integer(value); } else { throw new IllegalArgumentException("An undefined value type was found"); } objIndex++; } builder.addAll(values); SimpleFeature feature = builder.buildFeature(featureType.getTypeName() + "." + featureId); featureId++; newCollection.add(feature); } bR.close(); pm.done(); return newCollection; } /** *

* The easy way to create a shapefile from attributes and geometries *

*

* NOTE: this doesn't support date attributes *

* * @param shapeFilePath the shapefile name * @param crs the destination crs * @param fet the featurecollection * @throws IOException */ public static synchronized boolean collectionToShapeFile( String shapeFilePath, CoordinateReferenceSystem crs, SimpleFeatureCollection fet ) throws IOException { // Create the file you want to write to File file = null; if (shapeFilePath.toLowerCase().endsWith(".shp")) { //$NON-NLS-1$ file = new File(shapeFilePath); } else { file = new File(shapeFilePath + ".shp"); //$NON-NLS-1$ } ShapefileDataStoreFactory factory = new ShapefileDataStoreFactory(); Map create = new HashMap(); create.put("url", file.toURI().toURL()); ShapefileDataStore newDataStore = (ShapefileDataStore) factory.createNewDataStore(create); newDataStore.createSchema(fet.getSchema()); if (crs != null) newDataStore.forceSchemaCRS(crs); Transaction transaction = new DefaultTransaction(); FeatureStore featureStore = (FeatureStore) newDataStore .getFeatureSource(); featureStore.setTransaction(transaction); try { featureStore.addFeatures(fet); transaction.commit(); } catch (Exception problem) { problem.printStackTrace(); transaction.rollback(); } finally { transaction.close(); } return true; } /** * @param name the shapefile name * @param fieldsSpec to create other fields you can use a string like :
* "geom:MultiLineString,FieldName:java.lang.Integer"
* field name can not be over 10 characters use a ',' between each field
* field types can be : java.lang.Integer, java.lang.Long, // java.lang.Double, * java.lang.String or java.util.Date * @return * @throws Exception */ @SuppressWarnings("nls") public static synchronized ShapefileDataStore createShapeFileDatastore( String name, String fieldsSpec, CoordinateReferenceSystem crs ) throws Exception { // Create the file you want to write to File file = null; if (name.toLowerCase().endsWith(".shp")) { file = new File(name); } else { file = new File(name + ".shp"); } ShapefileDataStoreFactory factory = new ShapefileDataStoreFactory(); Map create = new HashMap(); create.put("url", file.toURI().toURL()); ShapefileDataStore myData = (ShapefileDataStore) factory.createNewDataStore(create); // Tell this shapefile what type of data it will store // Shapefile handle only : Point, MultiPoint, MultiLineString, // MultiPolygon SimpleFeatureType featureType = DataUtilities.createType(name, fieldsSpec); // Create the Shapefile (empty at this point) myData.createSchema(featureType); // Tell the DataStore what type of Coordinate Reference System (CRS) // to use myData.forceSchemaCRS(crs); return myData; } /** * Writes a featurecollection to a shapefile * * @param data the datastore * @param collection the featurecollection * @throws IOException */ private static synchronized boolean writeToShapefile( ShapefileDataStore data, SimpleFeatureCollection collection ) throws IOException { String featureName = data.getTypeNames()[0]; // there is only one in // a shapefile FeatureStore store = null; Transaction transaction = null; try { // Create the DefaultTransaction Object transaction = Transaction.AUTO_COMMIT; // Tell it the name of the shapefile it should look for in our // DataStore SimpleFeatureSource source = data.getFeatureSource(featureName); store = (FeatureStore) source; store.addFeatures(collection); data.getFeatureWriter(transaction); // TODO is this needed transaction.commit(); return true; } catch (Exception eek) { eek.printStackTrace(); transaction.rollback(); return false; } finally { transaction.close(); } } /** * Extracts features from a {@link FeatureCollection} into an {@link ArrayList}. * * @param collection the feature collection. * @return the list with the features or an empty list if no features present. */ public static List featureCollectionToList( SimpleFeatureCollection collection ) { List featuresList = new ArrayList(); if (collection == null) { return featuresList; } SimpleFeatureIterator featureIterator = collection.features(); while( featureIterator.hasNext() ) { SimpleFeature feature = featureIterator.next(); featuresList.add(feature); } featureIterator.close(); return featuresList; } /** * Extracts features from a {@link FeatureCollection} into an {@link ArrayList} of {@link FeatureMate}s. * * @param collection the feature collection. * @return the list with the features or an empty list if no features present. */ public static List featureCollectionToMatesList( SimpleFeatureCollection collection ) { List featuresList = new ArrayList(); if (collection == null) { return featuresList; } SimpleFeatureIterator featureIterator = collection.features(); while( featureIterator.hasNext() ) { SimpleFeature feature = featureIterator.next(); featuresList.add(new FeatureMate(feature)); } featureIterator.close(); return featuresList; } /** * Extracts features from a {@link FeatureCollection} into an {@link ArrayList} of its geometries. * * @param collection the feature collection. * @param doSubGeoms split the geometries in single geometries (ex. MultiLines in Lines). * @param userDataField if not null, the data in the field are put in the userData * field of the geometry. * @return the list with the geometries or an empty list if no features present. */ public static List featureCollectionToGeometriesList( SimpleFeatureCollection collection, boolean doSubGeoms, String userDataField ) { List geometriesList = new ArrayList(); if (collection == null) { return geometriesList; } SimpleFeatureIterator featureIterator = collection.features(); while( featureIterator.hasNext() ) { SimpleFeature feature = featureIterator.next(); Geometry geometry = (Geometry) feature.getDefaultGeometry(); if (doSubGeoms) { int numGeometries = geometry.getNumGeometries(); for( int i = 0; i < numGeometries; i++ ) { Geometry geometryN = geometry.getGeometryN(i); geometriesList.add(geometryN); if (userDataField != null) { Object attribute = feature.getAttribute(userDataField); geometryN.setUserData(attribute); } } } else { geometriesList.add(geometry); if (userDataField != null) { Object attribute = feature.getAttribute(userDataField); geometry.setUserData(attribute); } } } featureIterator.close(); return geometriesList; } /** * Getter for attributes of a feature. * *

If the attribute is not found, checks are done in non * case sensitive mode. * * @param feature the feature from which to get the attribute. * @param field the name of the field. * @return the attribute or null if none found. */ public static Object getAttributeCaseChecked( SimpleFeature feature, String field ) { Object attribute = feature.getAttribute(field); if (attribute == null) { attribute = feature.getAttribute(field.toLowerCase()); if (attribute != null) return attribute; attribute = feature.getAttribute(field.toUpperCase()); if (attribute != null) return attribute; // alright, last try, search for it SimpleFeatureType featureType = feature.getFeatureType(); field = findAttributeName(featureType, field); if (field != null) { return feature.getAttribute(field); } } return attribute; } /** * Find the name of an attribute, case insensitive. * * @param featureType te feature type to check. * @param field the case insensitive field name. * @return the real name of the field, or null, if none found. */ public static String findAttributeName( SimpleFeatureType featureType, String field ) { List attributeDescriptors = featureType.getAttributeDescriptors(); for( AttributeDescriptor attributeDescriptor : attributeDescriptors ) { String name = attributeDescriptor.getLocalName(); if (name.toLowerCase().equals(field.toLowerCase())) { return name; } } return null; } /** * Create a {@link Polygon} from an {@link Envelope}. * * @param envelope the envelope to convert. * @return the created polygon. */ public static Polygon envelopeToPolygon( Envelope2D envelope ) { double w = envelope.getMinX(); double e = envelope.getMaxX(); double s = envelope.getMinY(); double n = envelope.getMaxY(); Coordinate[] coords = new Coordinate[5]; coords[0] = new Coordinate(w, n); coords[1] = new Coordinate(e, n); coords[2] = new Coordinate(e, s); coords[3] = new Coordinate(w, s); coords[4] = new Coordinate(w, n); GeometryFactory gf = GeometryUtilities.gf(); LinearRing linearRing = gf.createLinearRing(coords); Polygon polygon = gf.createPolygon(linearRing, null); return polygon; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy