//$HeadURL$ /*---------------- FILE HEADER ------------------------------------------ This file is part of deegree. Copyright (C) 2001-2008 by: Department of Geography, University of Bonn http://www.giub.uni-bonn.de/deegree/ lat/lon GmbH http://www.lat-lon.de 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; either version 2.1 of the License, or (at your option) any later version. 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. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Contact: Andreas Poth lat/lon GmbH Aennchenstr. 19 53177 Bonn Germany E-Mail: poth@lat-lon.de Prof. Dr. Klaus Greve Department of Geography University of Bonn Meckenheimer Allee 166 53115 Bonn Germany E-Mail: greve@giub.uni-bonn.de ---------------------------------------------------------------------------*/ package org.deegree.igeo.commands.digitize; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.UUID; import org.deegree.datatypes.QualifiedName; import org.deegree.igeo.ApplicationContainer; import org.deegree.igeo.commands.CommandHelper; import org.deegree.igeo.dataadapter.FeatureAdapter; import org.deegree.igeo.i18n.Messages; import org.deegree.igeo.mapmodel.Layer; import org.deegree.igeo.mapmodel.MapModel; import org.deegree.kernel.Command; import org.deegree.model.feature.DefaultFeature; import org.deegree.model.feature.Feature; import org.deegree.model.feature.FeatureCollection; import org.deegree.model.feature.FeatureFactory; import org.deegree.model.feature.FeatureProperty; import org.deegree.model.spatialschema.Geometry; import org.deegree.model.spatialschema.GeometryException; import org.deegree.model.spatialschema.GeometryFactory; import org.deegree.model.spatialschema.MultiSurface; import org.deegree.model.spatialschema.Position; import org.deegree.model.spatialschema.Ring; import org.deegree.model.spatialschema.Surface; import org.deegree.model.spatialschema.SurfaceInterpolationImpl; /** * {@link Command} implementation for cutting hole into polygon using overlayed polygons of the same layer * * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a> * @author last edited by: $Author$ * * @version. $Revision$, $Date$ */ public class CuttingPolygonHoleCommand extends AbstractPolygonHoleCommand { private static QualifiedName name = new QualifiedName( "Cutting Polygon Hole" ); private boolean performed = false; private FeatureCollection featureCollection; private FeatureCollection oldFeatureCollection; private Feature root; private QualifiedName geomProperty; private ApplicationContainer<?> appCont; /** * * @param appCont */ public void setApplicationContainer( ApplicationContainer<?> appCont ) { this.appCont = appCont; } /** * * @param geomProperty */ public void setGeometryProperty( QualifiedName geomProperty ) { this.geomProperty = geomProperty; } /** * * @param featureCollection */ public void setFeatureCollection( FeatureCollection featureCollection ) { this.featureCollection = featureCollection; // create a deep copy for undoing Feature[] features = this.featureCollection.toArray(); for ( int i = 0; i < features.length; i++ ) { try { features[i] = ( (DefaultFeature) features[i] ).cloneDeep(); } catch ( CloneNotSupportedException e ) { // TODO Auto-generated catch block e.printStackTrace(); } } this.oldFeatureCollection = FeatureFactory.createFeatureCollection( UUID.randomUUID().toString(), features ); } /* * (non-Javadoc) * * @see org.deegree.kernel.Command#execute() */ public void execute() throws Exception { if ( featureCollection != null && featureCollection.size() > 1 ) { if ( geomProperty == null ) { geomProperty = CommandHelper.findGeomProperty( featureCollection.getFeature( 0 ) ); } Feature[] features = featureCollection.toArray(); // find root surface root = features[0]; Geometry rootGeom = (Geometry) root.getProperties( geomProperty )[0].getValue(); int idx = 0; for ( int i = 1; i < features.length; i++ ) { Geometry otherGeom = (Geometry) features[i].getProperties( geomProperty )[0].getValue(); if ( otherGeom.contains( rootGeom ) ) { root = features[i]; rootGeom = otherGeom; idx = i; } else if ( !rootGeom.contains( otherGeom ) ) { throw new Exception( Messages.getMessage( appCont.getLocale(), "$MD11608" ) ); } } // check again for ( int i = 0; i < features.length; i++ ) { if ( i != idx ) { Geometry otherGeom = (Geometry) features[i].getProperties( geomProperty )[0].getValue(); if ( otherGeom.contains( rootGeom ) ) { throw new Exception( Messages.getMessage( appCont.getLocale(), "$MD11608" ) ); } } } // cut hole(s) Geometry resultGeom = null; if ( rootGeom instanceof Surface ) { resultGeom = handleSurface( features, idx, (Surface) rootGeom ); } else { Surface[] surfaces = ( (MultiSurface) rootGeom ).getAllSurfaces(); for ( int k = 0; k < surfaces.length; k++ ) { for ( int i = 0; i < features.length; i++ ) { if ( i != idx ) { Geometry geom = (Geometry) features[i].getProperties( geomProperty )[0].getValue(); if ( surfaces[k].contains( geom ) ) { surfaces[k] = handleSurface( new Feature[] { features[i] }, idx, surfaces[k] ); } } } } resultGeom = GeometryFactory.createMultiSurface( surfaces, rootGeom.getCoordinateSystem() ); } // update root feature and delete all other features (features that are now holes) setGeometryProperty( root, resultGeom ); // Layer layer = appCont.getMapModel( null ).getLayersSelectedForAction( MapModel.SELECTION_EDITING ).get( 0 ); // FeatureAdapter fa = (FeatureAdapter) layer.getDataAccess().get( 0 ); // fa.updateFeature( root ); // for ( int i = 0; i < features.length; i++ ) { // if ( i != idx ) { // fa.deleteFeature( features[i] ); // } // } } performed = true; fireCommandProcessedEvent(); } private Surface handleSurface( Feature[] features, int idx, Surface rootSurface ) throws Exception, GeometryException { Position[] exterior = rootSurface.getSurfaceBoundary().getExteriorRing().getPositions(); // collect old inner rings Ring[] rings = rootSurface.getSurfaceBoundary().getInteriorRings(); List<Position[]> interior = new ArrayList<Position[]>(); for ( Ring ring : rings ) { interior.add( ring.getPositions() ); } // add exterior rings of cutting surfaces as inner rings for ( int i = 0; i < features.length; i++ ) { if ( i != idx ) { Geometry geom = (Geometry) features[i].getProperties( geomProperty )[0].getValue(); if ( geom instanceof Surface ) { Surface surface = (Surface) geom; Position[] tmp = surface.getSurfaceBoundary().getExteriorRing().getPositions(); if ( isClockwise( tmp ) ) { invertPositionOrder( tmp ); } interior.add( tmp ); } else if ( geom instanceof MultiSurface ) { Surface[] surfaces = ( (MultiSurface) geom ).getAllSurfaces(); for ( Surface surface : surfaces ) { Position[] tmp = surface.getSurfaceBoundary().getExteriorRing().getPositions(); if ( isClockwise( tmp ) ) { invertPositionOrder( tmp ); } interior.add( tmp ); } } else { throw new Exception( Messages.getMessage( appCont.getLocale(), "$MD11609" ) ); } } } Position[][] innerRings = (Position[][]) interior.toArray( new Position[interior.size()][] ); return GeometryFactory.createSurface( exterior, innerRings, new SurfaceInterpolationImpl(), rootSurface.getCoordinateSystem() ); } /** * * @param feature * @param geom */ protected void setGeometryProperty( Feature feature, Geometry geom ) { FeatureProperty fp = feature.getProperties( geomProperty )[0]; fp.setValue( geom ); feature.setProperty( fp, 0 ); } /* * (non-Javadoc) * * @see org.deegree.kernel.Command#getName() */ public QualifiedName getName() { return name; } /* * (non-Javadoc) * * @see org.deegree.kernel.Command#getResult() */ public Object getResult() { return root; } /* * (non-Javadoc) * * @see org.deegree.kernel.Command#undo() */ public void undo() throws Exception { if ( performed ) { Layer layer = appCont.getMapModel( null ).getLayersSelectedForAction( MapModel.SELECTION_EDITING ).get( 0 ); FeatureAdapter fa = (FeatureAdapter) layer.getDataAccess().get( 0 ); fa.deleteFeature( root ); Iterator<Feature> iter = oldFeatureCollection.iterator(); while ( iter.hasNext() ) { Feature feature = (Feature) iter.next(); fa.insertFeature( feature ); } performed = false; } } }