/* Spatial Operations & Editing Tools for uDig
*
* Axios Engineering under a funding contract with:
* Diputación Foral de Gipuzkoa, Ordenación Territorial
*
* http://b5m.gipuzkoa.net
* http://www.axios.es
*
* (C) 2006, Diputación Foral de Gipuzkoa, Ordenación Territorial (DFG-OT).
* DFG-OT agrees to licence under Lesser General Public License (LGPL).
*
* 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 es.axios.udig.ui.editingtools.trim.internal;
import java.io.IOException;
import net.refractions.udig.project.ILayer;
import net.refractions.udig.project.command.UndoableMapCommand;
import net.refractions.udig.tools.edit.Behaviour;
import net.refractions.udig.tools.edit.EditToolHandler;
import net.refractions.udig.tools.edit.support.GeometryCreationUtil;
import net.refractions.udig.tools.edit.support.PrimitiveShape;
import org.geotools.factory.CommonFactoryFinder;
import org.geotools.feature.FeatureCollection;
import org.geotools.filter.IllegalFilterException;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.filter.Filter;
import org.opengis.filter.FilterFactory2;
import org.opengis.filter.spatial.Intersects;
import org.opengis.referencing.operation.OperationNotFoundException;
import org.opengis.referencing.operation.TransformException;
import com.vividsolutions.jts.geom.LineString;
import es.axios.udig.ui.commons.util.DialogUtil;
import es.axios.udig.ui.commons.util.LayerUtil;
import es.axios.udig.ui.editingtools.internal.commands.EditingToolsCommandFactory;
import es.axios.udig.ui.editingtools.internal.i18n.Messages;
import es.axios.udig.ui.editingtools.trim.TrimTool;
/**
* {@link Behaviour} to use the blackboard's linestring as a trimming line for the {@link TrimTool}
* <p>
* Requirements:
* <ul>
* <li>Current Shape is not null</li>
* </ul>
* </p>
* <p>
* Action: {@link #getCommand(EditToolHandler)} returns the command initialized to trim the lines at
* the right of the one in the blackboard.
* </p>
*
* @author Gabriel Roldan (www.axios.es)
* @author Mauricio Pazos (www.axios.es)
* @since 1.1.0
*/
public class TrimGeometryBehaviour implements Behaviour {
private EditingToolsCommandFactory commandFactory;
public TrimGeometryBehaviour( EditingToolsCommandFactory commandFactory ) {
this.commandFactory = commandFactory;
}
/**
* Valid if current shape is not null and has at least two coordinates
*/
public boolean isValid( EditToolHandler handler ) {
PrimitiveShape currentShape = handler.getCurrentShape();
if (currentShape == null) {
return false;
}
int nCoords = currentShape.getNumCoords();
return nCoords > 1;
}
public UndoableMapCommand getCommand( EditToolHandler handler ) {
final ILayer selectedLayer = handler.getContext().getSelectedLayer();
LineString trimmingLineInLayerCrs;
try {
trimmingLineInLayerCrs = getTrimmingLineInLayerCrs(handler);
} catch (OperationNotFoundException e) {
throw (RuntimeException) new RuntimeException("Cannot reproject trim line from "
+ "layer's crs to map's crs").initCause(e);
} catch (TransformException e) {
throw (RuntimeException) new RuntimeException("Cannot reproject trim line from "
+ "layer's crs to map's crs").initCause(e);
}
FeatureCollection<SimpleFeatureType, SimpleFeature> featuresToTrim;
try {
featuresToTrim = getFeaturesToTrim(selectedLayer, trimmingLineInLayerCrs);
} catch (OperationNotFoundException e) {
throw new IllegalStateException( e.getMessage(), e );
} catch (IOException e) {
throw new IllegalStateException( e.getMessage(), e );
} catch (TransformException e) {
throw new IllegalStateException( e.getMessage(), e );
}
featuresToTrim.size();
UndoableMapCommand trimCommand = commandFactory
.createTrimFeaturesCommand(handler,
selectedLayer,
featuresToTrim,
trimmingLineInLayerCrs);
return trimCommand;
}
private FeatureCollection<SimpleFeatureType, SimpleFeature> getFeaturesToTrim( ILayer selectedLayer, LineString trimmingLine ) throws IOException, OperationNotFoundException, TransformException {
Filter extraFilter = createTrimmingLineFilter(selectedLayer, trimmingLine);
FeatureCollection<SimpleFeatureType, SimpleFeature> selection = LayerUtil.getSelectedFeatures(selectedLayer,
extraFilter);
return selection;
}
/**
* Returns the line drawn as the trimming line, transformed to JTS LineString, in the selected
* layer's CRS
*
* @param handler the {@link EditToolHandler} from where to grab the current shape (the one
* drawn as the cutting line)
* @return
* @throws TransformException
* @throws OperationNotFoundException
*/
private LineString getTrimmingLineInLayerCrs( EditToolHandler handler ) throws OperationNotFoundException, TransformException {
final PrimitiveShape currentShape = handler.getCurrentShape();
final LineString line = GeometryCreationUtil.createGeom(LineString.class, currentShape,true);
return line;
}
public void handleError( EditToolHandler handler, Throwable error, UndoableMapCommand command ) {
// TODO: log through this plugin
// EditPlugin.log("", error); //$NON-NLS-1$
DialogUtil.openError(Messages.TrimGeometryBehaviour_operation_failed, error.getMessage());
}
private Filter createTrimmingLineFilter( ILayer selectedLayer, LineString trimmingLineInLayerCrs ) throws OperationNotFoundException, TransformException {
Filter filter = selectedLayer.getFilter();
FilterFactory2 ff = CommonFactoryFinder.getFilterFactory2(null);
Intersects intersectsFilter;
try {
// final CoordinateReferenceSystem geomCrs;
// geomCrs = (CoordinateReferenceSystem) trimmingLineInLayerCrs.getUserData();
// final CoordinateReferenceSystem reprojectCrs = LayerUtil.getLayerCrs(selectedLayer);
// final Geometry literal = GeoToolsUtils.reproject(trimmingLineInLayerCrs, geomCrs,
// reprojectCrs);
SimpleFeatureType schema = selectedLayer.getSchema();
String typeName = schema.getDefaultGeometry().getLocalName();
intersectsFilter = ff.intersects( ff.property(typeName), ff.literal(trimmingLineInLayerCrs));
} catch (IllegalFilterException e) {
throw (RuntimeException) new RuntimeException().initCause(e);
}
if (Filter.EXCLUDE.equals(filter)) {
filter = intersectsFilter;
} else {
filter = ff.and( filter, intersectsFilter);
}
return filter;
}
}