/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2014, 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.spatialstatistics.operations;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.data.simple.SimpleFeatureIterator;
import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.process.spatialstatistics.storage.IFeatureInserter;
import org.geotools.util.Converters;
import org.geotools.util.logging.Logging;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.filter.expression.Expression;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.Point;
import com.vividsolutions.jts.operation.union.CascadedPolygonUnion;
import com.vividsolutions.jts.shape.random.RandomPointsBuilder;
/**
* Creates a random point featurecollection.
*
* @author Minpa Lee, MangoSystem
*
* @source $URL$
*
*/
public class RandomPointsOperation extends GeneralOperation {
protected static final Logger LOGGER = Logging.getLogger(RandomPointsOperation.class);
private com.vividsolutions.jts.shape.random.RandomPointsBuilder builder;
private CoordinateReferenceSystem crs;
public RandomPointsOperation() {
}
public SimpleFeatureCollection execute(ReferencedEnvelope extent, int pointCount)
throws IOException {
builder = new RandomPointsBuilder(gf);
crs = extent.getCoordinateReferenceSystem();
builder.setExtent(extent);
return execute(pointCount);
}
public SimpleFeatureCollection execute(SimpleFeatureCollection boundsSource, int pointCount)
throws IOException {
builder = new RandomPointsBuilder(gf);
crs = boundsSource.getSchema().getCoordinateReferenceSystem();
Geometry maskPolygon = unionFeatures(boundsSource);
if (maskPolygon == null || maskPolygon.isEmpty()) {
builder.setExtent(boundsSource.getBounds());
LOGGER.log(Level.WARNING,
"Failed to create mask polygon, random points builder will use feature's boundary");
} else {
builder.setExtent(maskPolygon);
}
return execute(pointCount);
}
private SimpleFeatureCollection execute(int pointCount) throws IOException {
builder.setNumPoints(pointCount);
SimpleFeatureType schema = createSchema(false);
IFeatureInserter featureWriter = getFeatureWriter(schema);
try {
Geometry multiPoints = builder.getGeometry();
for (int i = 0; i < multiPoints.getNumGeometries(); i++) {
Point point = (Point) multiPoints.getGeometryN(i);
// create feature and set geometry
SimpleFeature newFeature = featureWriter.buildFeature();
newFeature.setAttribute("weight", 1);
newFeature.setDefaultGeometry(point);
featureWriter.write(newFeature);
}
} catch (Exception e) {
featureWriter.rollback(e);
} finally {
featureWriter.close();
}
return featureWriter.getFeatureCollection();
}
public SimpleFeatureCollection executeperFeatures(SimpleFeatureCollection polygonFeatures,
int pointCount) throws IOException {
return executeperFeatures(polygonFeatures, ff.literal(pointCount));
}
public SimpleFeatureCollection executeperFeatures(SimpleFeatureCollection polygonFeatures,
Expression expression) throws IOException {
builder = new RandomPointsBuilder(gf);
crs = polygonFeatures.getSchema().getCoordinateReferenceSystem();
SimpleFeatureType schema = createSchema(true);
IFeatureInserter featureWriter = getFeatureWriter(schema);
SimpleFeatureIterator featureIter = polygonFeatures.features();
try {
while (featureIter.hasNext()) {
SimpleFeature feature = featureIter.next();
Geometry geometry = (Geometry) feature.getDefaultGeometry();
if (geometry == null || geometry.isEmpty()) {
continue;
}
Object value = expression.evaluate(feature);
if (value == null) {
continue;
}
Integer pointCount = Converters.convert(value, Integer.class);
if (pointCount == null || pointCount == 0) {
continue;
}
builder.setExtent(geometry);
builder.setNumPoints(pointCount);
Geometry multiPoints = builder.getGeometry();
for (int i = 0; i < multiPoints.getNumGeometries(); i++) {
Point point = (Point) multiPoints.getGeometryN(i);
// create feature and set geometry
SimpleFeature newFeature = featureWriter.buildFeature();
newFeature.setAttribute("id", feature.getID());
newFeature.setAttribute("weight", 1);
newFeature.setDefaultGeometry(point);
featureWriter.write(newFeature);
}
}
} catch (Exception e) {
featureWriter.rollback(e);
} finally {
featureWriter.close(featureIter);
}
return featureWriter.getFeatureCollection();
}
private SimpleFeatureType createSchema(boolean createID) {
SimpleFeatureTypeBuilder typeBuilder = new SimpleFeatureTypeBuilder();
typeBuilder.setName("RandomPoints");
typeBuilder.add("geom", Point.class, crs);
if (createID) {
typeBuilder.add("id", String.class);
}
typeBuilder.add("weight", Integer.class);
return typeBuilder.buildFeatureType();
}
private Geometry unionFeatures(SimpleFeatureCollection inputFeatures) {
List<Geometry> geometries = new ArrayList<Geometry>();
SimpleFeatureIterator featureIter = null;
try {
featureIter = inputFeatures.features();
while (featureIter.hasNext()) {
SimpleFeature feature = featureIter.next();
Geometry geometry = (Geometry) feature.getDefaultGeometry();
if (geometry == null || geometry.isEmpty()) {
continue;
}
geometries.add(geometry);
}
} finally {
if (featureIter != null)
featureIter.close();
}
if (geometries.size() == 0) {
return null;
} else if (geometries.size() == 1) {
return geometries.iterator().next();
}
com.vividsolutions.jts.operation.union.CascadedPolygonUnion unionOp = null;
unionOp = new CascadedPolygonUnion(geometries);
return unionOp.union();
}
}