//$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.awt.geom.Line2D; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Locale; 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.kernel.CommandException; import org.deegree.model.crs.CoordinateSystem; 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.SurfaceInterpolationImpl; /** * {@link Command} implementation for inserting a new vertex into 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 InsertVertexCommand extends MoveVertexCommand { private QualifiedName name = new QualifiedName( "Insert Vertex" ); private double minDistance = Double.MAX_VALUE; private boolean inserted = false; /** * * @param appCont * @param feature * @param geomProperty * @param sourcePoint */ public InsertVertexCommand( ApplicationContainer<?> appCont, Feature feature, QualifiedName geomProperty, Point sourcePoint ) { super( appCont, feature, geomProperty, sourcePoint, null ); } /* * (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(); if ( geom instanceof Point ) { throw new CommandException( Messages.getMessage( Locale.getDefault(), "$MD10330" ) ); } else if ( geom instanceof Curve ) { geom = handleCurve( (Curve) geom ); } else if ( geom instanceof Surface ) { geom = handleSurface( (Surface) geom ); } else if ( geom instanceof MultiPoint ) { throw new CommandException( Messages.getMessage( Locale.getDefault(), "$MD10331" ) ); } else if ( geom instanceof MultiCurve ) { geom = handleMultiCurve( (MultiCurve) geom ); } else if ( geom instanceof MultiSurface ) { geom = handleMultiSurface( (MultiSurface) geom ); } 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 Geometry handleCurve( Curve curve ) throws GeometryException { Position[] positions = curve.getAsLineString().getPositions(); double distance = Double.MAX_VALUE; int index = -1; for ( int i = 0; i < positions.length - 1; i++ ) { double tmp = Line2D.ptSegDist( positions[i].getX(), positions[i].getY(), positions[i + 1].getX(), positions[i + 1].getY(), sourcePoint.getX(), sourcePoint.getY() ); if ( tmp < distance && tmp < minDistance ) { distance = tmp; index = i; } } if ( index > -1 ) { curve = insertVertexintoCurve( curve.getCoordinateSystem(), curve, index ); } return curve; } private Geometry handleMultiCurve( MultiCurve mcurve ) throws GeometryException { Curve[] curves = mcurve.getAllCurves(); int curveIndex = -1; double distance = Double.MAX_VALUE; int index = -1; for ( int j = 0; j < curves.length; j++ ) { Position[] positions = curves[j].getAsLineString().getPositions(); for ( int i = 0; i < positions.length - 1; i++ ) { double tmp = Line2D.ptSegDist( positions[i].getX(), positions[i].getY(), positions[i + 1].getX(), positions[i + 1].getY(), sourcePoint.getX(), sourcePoint.getY() ); if ( tmp < distance && tmp < minDistance ) { distance = tmp; index = i; curveIndex = j; } } } if ( index > -1 ) { curves[curveIndex] = insertVertexintoCurve( mcurve.getCoordinateSystem(), curves[curveIndex], index ); mcurve = GeometryFactory.createMultiCurve( curves ); } return mcurve; } private Curve insertVertexintoCurve( CoordinateSystem crs, Curve curve, int index ) throws GeometryException { Position[] positions = curve.getAsLineString().getPositions(); List<Position> list = new ArrayList<Position>( positions.length ); for ( int i = 0; i < positions.length; i++ ) { list.add( positions[i] ); if ( i == index ) { // add new vertex list.add( sourcePoint.getPosition() ); } } inserted = true; positions = list.toArray( new Position[list.size()] ); return GeometryFactory.createCurve( positions, crs ); } private Geometry handleSurface( Surface surface ) throws GeometryException { List<Position[]> rings = new ArrayList<Position[]>(); rings.add( surface.getSurfaceBoundary().getExteriorRing().getPositions() ); Ring[] inner = surface.getSurfaceBoundary().getInteriorRings(); for ( Ring ring : inner ) { rings.add( ring.getPositions() ); } int ringIndex = -1; double distance = Double.MAX_VALUE; int index = -1; for ( int j = 0; j < rings.size(); j++ ) { Position[] positions = rings.get( j ); for ( int i = 0; i < positions.length - 1; i++ ) { double tmp = Line2D.ptSegDist( positions[i].getX(), positions[i].getY(), positions[i + 1].getX(), positions[i + 1].getY(), sourcePoint.getX(), sourcePoint.getY() ); if ( tmp < distance && tmp < minDistance ) { distance = tmp; index = i; ringIndex = j; } } } if ( index > -1 ) { surface = insertVertexIntoSurface( surface, rings, ringIndex, index ); } return surface; } private Surface insertVertexIntoSurface( Surface surface, List<Position[]> rings, int ringIndex, int index ) throws GeometryException { Position[] positions = rings.get( ringIndex ); List<Position> list = new ArrayList<Position>( positions.length ); for ( int i = 0; i < positions.length; i++ ) { list.add( positions[i] ); if ( i == index ) { // add new vertex list.add( sourcePoint.getPosition() ); } } positions = list.toArray( new Position[list.size()] ); rings.set( ringIndex, positions ); Position[] exteriorRing = rings.remove( 0 ); Position[][] interiorRings = rings.toArray( new Position[rings.size()][] ); inserted = true; return GeometryFactory.createSurface( exteriorRing, interiorRings, new SurfaceInterpolationImpl(), surface.getCoordinateSystem() ); } private Geometry handleMultiSurface( MultiSurface msurface ) throws GeometryException { int surfaceIndex = -1; int ringIndex = -1; int index = -1; double distance = Double.MAX_VALUE; Surface[] surfaces = msurface.getAllSurfaces(); for ( int k = 0; k < surfaces.length; k++ ) { List<Position[]> rings = new ArrayList<Position[]>(); rings.add( surfaces[k].getSurfaceBoundary().getExteriorRing().getPositions() ); Ring[] inner = surfaces[k].getSurfaceBoundary().getInteriorRings(); for ( Ring ring : inner ) { rings.add( ring.getPositions() ); } for ( int j = 0; j < rings.size(); j++ ) { Position[] positions = rings.get( j ); for ( int i = 0; i < positions.length - 1; i++ ) { double tmp = Line2D.ptSegDist( positions[i].getX(), positions[i].getY(), positions[i + 1].getX(), positions[i + 1].getY(), sourcePoint.getX(), sourcePoint.getY() ); if ( tmp < distance && tmp < minDistance ) { distance = tmp; index = i; ringIndex = j; surfaceIndex = k; } } } } if ( index > -1 ) { List<Position[]> rings = new ArrayList<Position[]>(); rings.add( surfaces[surfaceIndex].getSurfaceBoundary().getExteriorRing().getPositions() ); Ring[] inner = surfaces[surfaceIndex].getSurfaceBoundary().getInteriorRings(); for ( Ring ring : inner ) { rings.add( ring.getPositions() ); } surfaces[surfaceIndex] = insertVertexIntoSurface( surfaces[surfaceIndex], rings, ringIndex, index ); msurface = GeometryFactory.createMultiSurface( surfaces ); } return msurface; } /* * (non-Javadoc) * * @see org.deegree.igeo.commands.MoveVertexCommand#getName() */ @Override public QualifiedName getName() { return name; } /* * (non-Javadoc) * * @see org.deegree.igeo.commands.MoveVertexCommand#undo() */ @Override public void undo() throws Exception { if ( performed && inserted ) { DeleteVertexCommand dvc = new DeleteVertexCommand( appCont, this.featureCollection, geomProperty, sourcePoint ); dvc.execute(); performed = false; } } }