package net.refractions.linecleaner.cleansing;
import java.io.IOException;
import net.refractions.linecleaner.LoggingSystem;
import net.refractions.udig.project.internal.Map;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.geotools.data.DefaultQuery;
import org.geotools.data.FeatureStore;
import org.geotools.data.Query;
import org.geotools.feature.AttributeType;
import org.geotools.feature.Feature;
import org.geotools.filter.FidFilter;
import org.geotools.filter.Filter;
import org.geotools.filter.FilterFactoryFinder;
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.simplify.DouglasPeuckerLineSimplifier;
/**
* Runs over every Feature in a FeatureStore and processes it
* using an implementation of the Douglas Peucker algorithm.
*
* @author rgould
*/
public class DouglasPeuckerProcessor extends AbstractProcessor {
public static final double DEFAULT_DISTANCE_TOLERANCE = 5;
double distanceTolerance;
LoggingSystem loggingSystem = LoggingSystem.getInstance();
public DouglasPeuckerProcessor(Map map, FeatureStore featureStore, double distanceTolerance) {
super(map, featureStore);
this.distanceTolerance = distanceTolerance;
}
protected void runInternal(IProgressMonitor monitor, PauseMonitor pauseMonitor) throws IOException {
if (monitor == null) monitor = new NullProgressMonitor();
loggingSystem.setCurrentAction(LoggingSystem.DOUGLAS_PEUCKER);
loggingSystem.begin();
int start = featureStore.getCount(Query.ALL);
monitor.beginTask("", start);
monitor.subTask("Performing Douglas-Peucker vertex removal");
MemoryFeatureIterator iter = new MemoryFeatureIterator(featureStore, map,
new DefaultQuery(featureStore.getSchema().getTypeName(), Filter.NONE,
new String[] { featureStore.getSchema().getDefaultGeometry().getName() }));
// FeatureIterator iter = featureStore.getFeatures().features();
try {
while (iter.hasNext()) {
monitor.worked(1);
if (monitor.isCanceled()) {
break;
}
pauseIfNecessary(pauseMonitor);
Feature feature = iter.next();
// System.out.println("[[DPP]] begin processing feature " + feature.getID());
Geometry geom = feature.getDefaultGeometry();
Coordinate[] points = geom.getCoordinates();
// System.out.println("BEFORE Geom: " + geom);
int before = points.length;
// System.out.println("BEFORE Coord count: " + points.length);
points = DouglasPeuckerLineSimplifier.simplify(points, distanceTolerance);
// System.out.println("AFTER Coord count: " + points.length);
int after = before - points.length;
if (after > 0) {
// loggingSystem.modify(feature, "Removed "+after+" coordinates.");
}
GeometryFactory factory = new GeometryFactory();
geom = factory.createMultiLineString(new LineString[] { factory.createLineString(points) });
// System.out.println("AFTER Geom: " + geom);
String xpath = feature.getFeatureType().getDefaultGeometry().getName();
AttributeType attributeType = feature.getFeatureType().getAttributeType(xpath);
String fid = feature.getID();
FidFilter fidFilter = FilterFactoryFinder.createFilterFactory().createFidFilter(fid);
this.featureStore.modifyFeatures(attributeType, geom, fidFilter);
}
} finally {
iter.close();
monitor.done();
}
int finish = start - featureStore.getCount(Query.ALL);
loggingSystem.finish(finish);
}
}