//$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.Locale; import org.deegree.datatypes.QualifiedName; import org.deegree.framework.util.GeometryUtils; 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.kernel.CommandException; import org.deegree.model.feature.Feature; import org.deegree.model.spatialschema.Curve; import org.deegree.model.spatialschema.Geometry; import org.deegree.model.spatialschema.GeometryException; import org.deegree.model.spatialschema.GeometryFactory; import org.deegree.model.spatialschema.MultiCurve; import org.deegree.model.spatialschema.MultiPoint; import org.deegree.model.spatialschema.MultiSurface; import org.deegree.model.spatialschema.Point; import org.deegree.model.spatialschema.Position; import org.deegree.model.spatialschema.Ring; import org.deegree.model.spatialschema.Surface; import org.deegree.model.spatialschema.SurfaceBoundary; import org.deegree.model.spatialschema.SurfaceInterpolationImpl; /** * {@link Command} implementation for deleting one or more vertices from a {@link Surface} or a {@link Curve} * * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a> * @author last edited by: $Author$ * * @version. $Revision$, $Date$ */ public class DeleteVertexCommand extends MoveVertexCommand { /** * * @param appCont * @param feature * @param geomProperty * @param sourcePoint */ public DeleteVertexCommand( ApplicationContainer<?> appCont, Feature feature, QualifiedName geomProperty, Point sourcePoint ) { super( appCont, feature, geomProperty, sourcePoint, null ); name = new QualifiedName( "Delete Vertex" ); } /* * (non-Javadoc) * * @see org.deegree.kernel.Command#execute() */ public void execute() throws Exception { Iterator<Feature> iter = featureCollection.iterator(); while ( iter.hasNext() ) { Feature feature = iter.next(); if ( geomProperty == null ) { geomProperty = CommandHelper.findGeomProperty( feature ); } Geometry geom = (Geometry) feature.getProperties( geomProperty )[0].getValue(); old.put( feature, geom ); boolean nearest = verticesOpt.handleNearest(); if ( geom instanceof Point ) { throw new CommandException( Messages.getMessage( Locale.getDefault(), "$MD10314" ) ); } else if ( geom instanceof Curve ) { geom = handleCurve( (Curve) geom, nearest ); } else if ( geom instanceof Surface ) { geom = handleSurface( (Surface) geom, nearest ); } else if ( geom instanceof MultiPoint ) { geom = handleMultiPoint( (MultiPoint) geom, nearest ); } else if ( geom instanceof MultiCurve ) { geom = handleMultiCurve( (MultiCurve) geom, nearest ); } else if ( geom instanceof MultiSurface ) { geom = handleMultiSurface( (MultiSurface) geom, nearest ); } setGeometryProperty( feature, geom ); Layer layer = appCont.getMapModel( null ).getLayersSelectedForAction( MapModel.SELECTION_EDITING ).get( 0 ); FeatureAdapter fa = (FeatureAdapter) layer.getDataAccess().get( 0 ); fa.updateFeature( feature ); } performed = true; fireCommandProcessedEvent(); } private List<Point> filterPoints( Point[] points, Point filterPoint ) { List<Point> pointList = new ArrayList<Point>( points.length ); for ( Point point : points ) { if ( point != filterPoint ) { pointList.add( point ); } } return pointList; } private Position[] filterPositions( Position[] positions, int minPos ) { double tolerance = sourcePoint.getTolerance(); List<Position> posList = new ArrayList<Position>( positions.length ); for ( Position position : positions ) { if ( GeometryUtils.distance( position, sourcePoint.getPosition() ) > tolerance ) { posList.add( position ); } } if ( posList.size() < minPos ) { throw new CommandException( Messages.getMessage( Locale.getDefault(), "$MD10315", minPos ) ); } return posList.toArray( new Position[posList.size()] ); } private Position[] filterPositions( Position[] positions, Position[] position, int minPos ) { List<Position> posList = new ArrayList<Position>( positions.length ); for ( Position position2 : positions ) { if ( position.length == 1 ) { if ( position2 != position[0] ) { posList.add( position2 ); } } else { if ( position2 != position[0] && position2 != position[1] ) { posList.add( position2 ); } } } if ( posList.size() < minPos ) { throw new CommandException( Messages.getMessage( Locale.getDefault(), "$MD10315", minPos ) ); } if ( position.length == 2 ) { // first an last point of a ring has been removed so remaining positions // must be closed again posList.add( GeometryFactory.createPosition( posList.get( 0 ).getX(), posList.get( 0 ).getY(), posList.get( 0 ).getZ() ) ); } return posList.toArray( new Position[posList.size()] ); } /** * * @param feature * @param curve * @param nearest * @return * @throws GeometryException */ private Geometry handleCurve( Curve curve, boolean nearest ) throws GeometryException { Position[] positions = curve.getAsLineString().getPositions(); if ( nearest ) { // just remove position nearest nearest to clickpoint Position[] position = new Position[] { findNearest( positions ) }; positions = filterPositions( positions, position, 2 ); } else { positions = filterPositions( positions, 2 ); } return GeometryFactory.createCurve( positions, curve.getCoordinateSystem() ); } /** * * @param geom * @param nearest * @return * @throws GeometryException */ private Geometry handleMultiCurve( MultiCurve geom, boolean nearest ) throws GeometryException { Curve[] curves = geom.getAllCurves(); List<Curve> curveList = new ArrayList<Curve>( curves.length ); if ( nearest ) { // just remove position nearest nearest to clickpoint Position[][] positions = new Position[curves.length][]; for ( int i = 0; i < curves.length; i++ ) { positions[i] = curves[i].getAsLineString().getPositions(); } Position[] position = findNearest( positions ); for ( int i = 0; i < positions.length; i++ ) { positions[i] = filterPositions( positions[i], position, 0 ); if ( positions[i].length > 1 ) { curveList.add( GeometryFactory.createCurve( positions[i], geom.getCoordinateSystem() ) ); } } } else { for ( Curve curve : curves ) { Position[] positions = curve.getAsLineString().getPositions(); positions = filterPositions( positions, 0 ); if ( positions.length > 1 ) { curveList.add( GeometryFactory.createCurve( positions, geom.getCoordinateSystem() ) ); } } } if ( curveList.size() == 0 ) { throw new CommandException( Messages.getMessage( Locale.getDefault(), "$MD10316" ) ); } return GeometryFactory.createMultiCurve( curves ); } /** * * @param geom * @param nearest * @return */ private Geometry handleMultiPoint( MultiPoint geom, boolean nearest ) { Point[] points = geom.getAllPoints(); List<Point> pointList = new ArrayList<Point>( points.length ); double tolerance = sourcePoint.getTolerance(); if ( nearest ) { // just move position nearest to click point Point point = findNearest( points ); pointList = filterPoints( points, point ); } else { for ( Point point : points ) { if ( GeometryUtils.distance( point.getPosition(), sourcePoint.getPosition() ) > tolerance ) { pointList.add( point ); } } } if ( pointList.size() == 0 ) { throw new CommandException( Messages.getMessage( Locale.getDefault(), "$MD10317" ) ); } return GeometryFactory.createMultiPoint( points ); } /** * * @param geom * @param nearest * @return * @throws GeometryException */ private Geometry handleMultiSurface( MultiSurface geom, boolean nearest ) throws GeometryException { Surface[] surfaces = geom.getAllSurfaces(); List<Surface> surfaceList = new ArrayList<Surface>( surfaces.length ); if ( nearest ) { // just move position nearest to click point // find nearest position List<Position[]> list = new ArrayList<Position[]>(); for ( Surface surface : surfaces ) { SurfaceBoundary sb = surface.getSurfaceBoundary(); Ring[] inner = sb.getInteriorRings(); list.add( sb.getExteriorRing().getPositions() ); for ( int i = 0; i < inner.length; i++ ) { list.add( inner[i].getPositions() ); } } Position[][] positions = list.toArray( new Position[list.size()][] ); Position[] position = findNearest( positions ); // delete nearest position for ( Surface surface : surfaces ) { SurfaceBoundary sb = surface.getSurfaceBoundary(); Position[] ext = sb.getExteriorRing().getPositions(); ext = validateRing( filterPositions( ext, position, 4 ) ); Ring[] inner = sb.getInteriorRings(); List<Position[]> innerList = new ArrayList<Position[]>( inner.length ); for ( Ring ring : inner ) { Position[] in = ring.getPositions(); in = filterPositions( in, position, 0 ); if ( in.length > 3 ) { innerList.add( validateRing( in ) ); } } Position[][] innerPos = innerList.toArray( new Position[innerList.size()][] ); surfaceList.add( GeometryFactory.createSurface( ext, innerPos, new SurfaceInterpolationImpl(), surface.getCoordinateSystem() ) ); } } else { for ( Surface surface : surfaces ) { surfaceList.add( (Surface) handleSurface( surface, false ) ); } } if ( surfaceList.size() == 0 ) { throw new CommandException( Messages.getMessage( Locale.getDefault(), "$MD10318" ) ); } return GeometryFactory.createMultiSurface( surfaceList.toArray( new Surface[surfaceList.size()] ) ); } /** * * @param surface * @param nearest * @return * @throws GeometryException */ private Geometry handleSurface( Surface surface, boolean nearest ) throws GeometryException { SurfaceBoundary sb = surface.getSurfaceBoundary(); Position[] ext = sb.getExteriorRing().getPositions(); Ring[] inner = sb.getInteriorRings(); List<Position[]> innerList = new ArrayList<Position[]>( inner.length ); if ( nearest ) { // just add external ring for searching nearest position innerList.add( ext ); for ( Ring ring : inner ) { Position[] in = ring.getPositions(); innerList.add( in ); } Position[][] tmp = innerList.toArray( new Position[innerList.size()][] ); Position[] position = findNearest( tmp ); ext = validateRing( filterPositions( tmp[0], position, 4 ) ); innerList.clear(); for ( int i = 1; i < tmp.length; i++ ) { Position[] in = filterPositions( tmp[i], position, 0 ); if ( in.length > 3 ) { innerList.add( validateRing( in ) ); } } } else { ext = validateRing( filterPositions( ext, 4 ) ); for ( Ring ring : inner ) { Position[] in = ring.getPositions(); in = filterPositions( in, 0 ); if ( in.length > 3 ) { innerList.add( validateRing( in ) ); } } } Position[][] innerPos = innerList.toArray( new Position[innerList.size()][] ); return GeometryFactory.createSurface( ext, innerPos, new SurfaceInterpolationImpl(), surface.getCoordinateSystem() ); } }