/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2008, Open Source Geospatial Foundation (OSGeo) * * 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.geotools.process.raster; import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.TreeMap; import org.geotools.coverage.grid.GridCoverage2D; import org.geotools.data.Parameter; import org.geotools.feature.FeatureCollection; import org.geotools.feature.NameImpl; import org.geotools.feature.simple.SimpleFeatureTypeBuilder; import org.geotools.process.impl.SingleProcessFactory; import org.geotools.text.Text; import org.opengis.feature.simple.SimpleFeatureType; import org.opengis.geometry.Envelope; import org.opengis.referencing.crs.CoordinateReferenceSystem; import org.opengis.util.InternationalString; import com.vividsolutions.jts.geom.Polygon; /** * Process for converting a raster regions to vector polygons. * <p> * The algorithm used is adapted from the GRASS raster to vector C code. It moves * a 2x2 kernel over the input raster. The data in the kernel are matched to a * table of the 12 possible configurations indicating which horizontal and/or * vertical pixel boundaries need to be traced. * * @author Michael Bedward, Jody Garnett * @since 2.6 * * @source $URL$ */ public class RasterToVectorFactory extends SingleProcessFactory { private static final String VERSION_STRING = "0.0.3"; /** Grid coverage to vectorize */ public static final Parameter<GridCoverage2D> RASTER = new Parameter<GridCoverage2D>( "raster", GridCoverage2D.class, Text.text("Raster"), Text.text("Grid coverage to vectorize")); /** Index of the band with data to vectorize */ public static final Parameter<Integer> BAND = new Parameter<Integer>( "band", Integer.class, Text.text("Band"), Text.text("Index of band to vectorize")); /** * Bounds (in world coordinates) ot the area to vectorize; if {@code null} * or absent the bounds of the coverage are used */ public static final Parameter<Envelope> BOUNDS = new Parameter<Envelope>( "bounds", Envelope.class, Text.text("Bounds"), Text.text("Bounds of the area to vectorize")); /** * The code(s) representing NODATA or outside the regions to be vectorized, * which will be supplied as a {@linkplain java.util.Collection} of Double values to the * {@linkplain RasterToVectorProcess#execute(java.util.Map, org.opengis.util.ProgressListener) } * method. */ public static final Parameter<Double> OUTSIDE = new Parameter<Double>( "nodata", Double.class, Text.text("NoData"), Text.text("Value representing NODATA or outside"), true, 1, -1, null, null); private static final Map<String, Parameter<?>> parameterInfo = new TreeMap<String, Parameter<?>>(); static { parameterInfo.put(RASTER.key, RASTER); parameterInfo.put(BAND.key, BAND); parameterInfo.put(BOUNDS.key, BOUNDS); parameterInfo.put(OUTSIDE.key, OUTSIDE); } /** * Parameter to retrieve the vectorized features from the results map returned * by {@linkplain RasterToVectorProcess#execute(java.util.Map, org.opengis.util.ProgressListener) } */ public static final Parameter<FeatureCollection> RESULT_FEATURES; private static final Map<String, Parameter<?>> resultInfo = new TreeMap<String, Parameter<?>>(); static { // Jody: we should be able to record the FeatureType here; but it is not well // defined in a public schema? SimpleFeatureType schema = getSchema(null); Map<String, Object> metadata = new HashMap<String, Object>(); metadata.put(Parameter.FEATURE_TYPE, schema); RESULT_FEATURES = new Parameter<FeatureCollection>( "features", FeatureCollection.class, Text.text("Features"), Text.text("Vectorized region boundaries as polygon features"), metadata); resultInfo.put(RESULT_FEATURES.key, RESULT_FEATURES); } public RasterToVectorFactory() { super(new NameImpl(GT_NAMESPACE, "RasterToVectorProcess")); } /** * Return a new instance of a RasterToVectorProcess */ public RasterToVectorProcess create() { return new RasterToVectorProcess(this); } /** * Get the description of this process * @return the string: Raster region to vector polygon conversion */ public InternationalString getDescription() { return Text.text("Raster region to vector polygon conversion"); } /** * Get a map of input parameters required by the * {@linkplain RasterToVectorProcess#execute(java.util.Map, org.opengis.util.ProgressListener) } * method * * @return a Map of input parameters */ public Map<String, Parameter<?>> getParameterInfo() { return Collections.unmodifiableMap(parameterInfo); } /** * Get information about the results that are returned as Map by the * {@linkplain RasterToVectorProcess#execute(java.util.Map, org.opengis.util.ProgressListener) } * method * @param parameters ignored at present so may be null * @return a Map of output parameters * @throws java.lang.IllegalArgumentException */ public Map<String, Parameter<?>> getResultInfo(Map<String, Object> parameters) throws IllegalArgumentException { return Collections.unmodifiableMap(resultInfo); } /** * Get the process title * @return title */ public InternationalString getTitle() { return Text.text("Vectorize raster regions"); } /** * Get the version of this process * @return version as a string */ public String getVersion() { return VERSION_STRING; } /** * Check if this process supports a progress listener * @return always returns true */ public boolean supportsProgress() { return true; } /** * Return the feature type of the vectorized polygons. * Note: We can generate a schema; but we need to know the CoordinateReferenceSystem. * * @param crs a coorindate reference system for the features * @return a new SimpleFeatureType with name: r2vPolygons and two attributes: * shape (Polygon) and code (Integer) */ public static SimpleFeatureType getSchema(CoordinateReferenceSystem crs) { SimpleFeatureTypeBuilder typeBuilder = new SimpleFeatureTypeBuilder(); typeBuilder.setName("r2vPolygons"); if (crs != null) { typeBuilder.setCRS(crs); } typeBuilder.add("shape", Polygon.class, (CoordinateReferenceSystem) null); typeBuilder.add("code", Integer.class); SimpleFeatureType type = typeBuilder.buildFeatureType(); return type; } }