/* 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) 2010, Diputación Foral de Gipuzkoa, Ordenación Territorial (DFG-OT). * DFG-OT agrees to license under General Public License (GPL). * * You can redistribute it and/or modify it under the terms of the * GNU 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 * General Public License for more details. */ package es.axios.udig.sextante.linetopolygon; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.text.MessageFormat; import net.refractions.udig.catalog.IGeoResource; import net.refractions.udig.project.ILayer; import net.refractions.udig.project.IMap; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.jface.operation.IRunnableWithProgress; import org.geotools.data.DataUtilities; import org.geotools.data.FeatureStore; import org.geotools.data.Transaction; import org.geotools.feature.FeatureCollection; import org.geotools.feature.FeatureIterator; import org.opengis.feature.simple.SimpleFeature; import org.opengis.feature.simple.SimpleFeatureType; import org.opengis.referencing.crs.CoordinateReferenceSystem; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.GeometryCollection; import com.vividsolutions.jts.geom.LineString; import com.vividsolutions.jts.geom.MultiLineString; import com.vividsolutions.jts.geom.MultiPolygon; import com.vividsolutions.jts.geom.Polygon; import es.axios.udig.sextante.task.LineToPolygonTask; import es.axios.udig.spatialoperations.ui.parameters.SOCommandException; import es.axios.udig.spatialoperations.ui.parameters.SimpleCommand; import es.axios.udig.spatialoperations.ui.taskmanager.SOFeatureStore; import es.axios.udig.ui.commons.mediator.AppGISMediator; import es.axios.udig.ui.commons.message.InfoMessage; import es.axios.udig.ui.commons.util.DialogUtil; import es.axios.udig.ui.commons.util.FeatureUtil; import es.axios.udig.ui.commons.util.LayerUtil; import es.axios.udig.ui.commons.util.MapUtil; import es.unex.sextante.exceptions.GeoAlgorithmExecutionException; /** * This command make use of the SimpleCommand and here are defined every text, * type, etc, that uses the SimplePresenter within the GUI. * * @author Mauricio Pazos (www.axios.es) * @author Aritz Davila (www.axios.es) * @since 1.3.0 */ public class LineToPolygonCommand extends SimpleCommand { protected static InfoMessage INITIAL_MESSAGE = new InfoMessage("Convert closed lines into polygons.", InfoMessage.Type.IMPORTANT_INFO); private IMap map; public LineToPolygonCommand() { super(INITIAL_MESSAGE); } @Override public void setGroupSourceText() { this.groupSourceText = "Source"; } @Override public void setGroupTargetInputsText() { this.groupTargetInputsText = "Result"; } @Override public void setLabelSourceLayerText() { this.labelSourceLayerText = "Source"; } @Override public void setOperationID() { this.operationID = "LineToPolygon"; } @Override public void setOperationName() { this.operationName = "LineToPolygon"; } @Override public void setTabItemAdvancedText() { this.tabItemAdvancedText = "Advanced"; } @Override public void setTabItemBasicText() { this.tabItemBasicText = "Basic"; } @Override public void setTargetLabelText() { this.targetLabelText = "Layer"; } @Override public void setTargetLabelToolTipText() { this.targetLabelToolTipText = "The layer where the result will go. Select an existent layer or write a new one."; } @Override public void setToolTipText() { this.toolTipText = "Convert lines to polygon."; } @Override protected Object[] getSourceGeomertyClass() { Object[] obj = new Object[] { LineString.class, MultiLineString.class }; return obj; } @Override protected Object[] getResultLayerGeometry() { Object[] obj; if (sourceLayer != null) { obj = new Object[1]; Class<? extends Geometry> sourceGeom = LayerUtil.getGeometryClass(this.sourceLayer); // is a geometry collection if (sourceGeom.getSuperclass().equals(GeometryCollection.class)) { obj[0] = MultiPolygon.class; } else { obj[0] = Polygon.class; } } else { obj = new Object[2]; obj[0] = Polygon.class; obj[1] = MultiPolygon.class; } return obj; } @Override public void executeOperation() throws SOCommandException { final NullProgressMonitor progress = new NullProgressMonitor(); this.map = sourceLayer.getMap(); // final FeatureStore<SimpleFeatureType, SimpleFeature> source = getFeatureStore(sourceLayer); try { progress.setTaskName("LinesToPolygon Spatial Operation"); String msg = MessageFormat.format("Doing lines to polygon of {0}", sourceLayer.getName()); progress.beginTask(msg, IProgressMonitor.UNKNOWN); IRunnableWithProgress runner = new IRunnableWithProgress() { public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { final FeatureStore<SimpleFeatureType, SimpleFeature> resultStore; LineToPolygonTask task = new LineToPolygonTask(source); try { task.run(); resultStore = task.getResult(); addFeaturesToTargetStore(resultStore); } catch (GeoAlgorithmExecutionException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (SOCommandException e) { e.printStackTrace(); } finally { map.getRenderManager().refresh(targetLayer, map.getBounds(progress)); progress.done(); } } }; DialogUtil.runInProgressDialog("Executing LinesToPolygon Operation", true, runner, true, true); } catch (Exception e) { throw new SOCommandException(e.getMessage()); } } private final FeatureStore<SimpleFeatureType, SimpleFeature> getFeatureStore(final ILayer layer) throws SOCommandException { assert layer != null; IGeoResource resource = layer.getGeoResource(); if (resource == null) { throw new SOCommandException("The layer does not have GeoResource"); } FeatureStore<SimpleFeatureType, SimpleFeature> store; try { store = resource.resolve(FeatureStore.class, new NullProgressMonitor()); return store; } catch (IOException e) { throw new SOCommandException(e.getMessage()); } } private final void addFeaturesToTargetStore(FeatureStore<SimpleFeatureType, SimpleFeature> resultStore) throws SOCommandException, IOException { FeatureStore<SimpleFeatureType, SimpleFeature> emptyTargetStore = null; if (this.targetLayer != null) { emptyTargetStore = this.getFeatureStore(this.targetLayer); } else { // create a new layer this.targetLayer = createNewLayer(); IGeoResource targetGeoResource = targetLayer.getGeoResource(); try { emptyTargetStore = targetGeoResource.resolve(FeatureStore.class, null); } catch (IOException e) { throw new SOCommandException(e.getMessage()); } } Transaction transactionOld = ((net.refractions.udig.project.internal.Map) this.map).getEditManagerInternal() .getTransaction(); SOFeatureStore soStore = new SOFeatureStore(emptyTargetStore, transactionOld); // add to target store. addToStore(soStore, resultStore); } /** * Add the features from the resultStore, which is the output off the * sextante operation; to the soStore. * * @param soStore * @param emptyTargetStore * @param resultStore * @throws IOException */ private void addToStore(SOFeatureStore soStore, FeatureStore<SimpleFeatureType, SimpleFeature> resultStore) throws IOException { FeatureCollection<SimpleFeatureType, SimpleFeature> collection = resultStore.getFeatures(); FeatureIterator<SimpleFeature> iter = collection.features(); SimpleFeatureType newFeatureType = soStore.getSchema(); Transaction transaction = soStore.getTransaction(); try { while (iter.hasNext()) { SimpleFeature sextanteFeature = iter.next(); SimpleFeature featureToAdd = FeatureUtil.createFeatureUsing(sextanteFeature, newFeatureType, (Geometry) sextanteFeature.getDefaultGeometry()); soStore.addFeatures(DataUtilities.collection(new SimpleFeature[] { featureToAdd })); transaction.commit(); } } catch (Exception ex) { transaction.rollback(); ex.printStackTrace(); } finally { collection.close(iter); transaction.close(); } } private final CoordinateReferenceSystem getTargetCRS() { if (this.targetLayer != null) { return this.targetLayer.getCRS(); } else { return getMapCRS(); } } private CoordinateReferenceSystem getMapCRS() { return MapUtil.getCRS(map); } private final ILayer createNewLayer() throws SOCommandException { FeatureStore<SimpleFeatureType, SimpleFeature> targetStore; try { SimpleFeatureType type = FeatureUtil.createFeatureType(this.sourceLayer.getSchema(), targetLayerName, getTargetCRS(), this.targetGeometryClass); IGeoResource targetGeoResource = AppGISMediator.createTempGeoResource(type); assert targetGeoResource != null; targetStore = targetGeoResource.resolve(FeatureStore.class, null); assert targetStore != null; ILayer newLayer = MapUtil.addLayerToMap((IMap) this.map, targetGeoResource); return newLayer; } catch (Exception e) { e.printStackTrace(); throw new SOCommandException(e); } } }