//$HeadURL$
/*---------------- FILE HEADER ------------------------------------------
This file is part of deegree.
Copyright (C) 2001-2012 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.views.swing.digitize;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Stroke;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.geom.GeneralPath;
import java.awt.geom.PathIterator;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.swing.BorderFactory;
import javax.swing.JLabel;
import javax.swing.JPanel;
import org.deegree.framework.log.ILogger;
import org.deegree.framework.log.LoggerFactory;
import org.deegree.framework.util.GeometryUtils;
import org.deegree.framework.util.StringTools;
import org.deegree.graphics.transformation.GeoTransform;
import org.deegree.igeo.ApplicationContainer;
import org.deegree.igeo.ChangeListener;
import org.deegree.igeo.ValueChangedEvent;
import org.deegree.igeo.commands.model.ZoomCommand;
import org.deegree.igeo.dataadapter.DataAccessAdapter;
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.igeo.modules.DefaultMapModule;
import org.deegree.igeo.modules.DigitizerModule;
import org.deegree.igeo.modules.IModule;
import org.deegree.igeo.settings.DigitizingLinesOpt;
import org.deegree.igeo.state.mapstate.EditState;
import org.deegree.igeo.state.mapstate.MapTool;
import org.deegree.igeo.state.mapstate.SelectState;
import org.deegree.igeo.state.mapstate.ToolState;
import org.deegree.igeo.state.mapstate.EditState.CreatePointFeatureState;
import org.deegree.igeo.state.mapstate.SelectState.RectangleSelectState;
import org.deegree.igeo.views.DialogFactory;
import org.deegree.igeo.views.DrawingPane;
import org.deegree.igeo.views.GeoDrawingPane;
import org.deegree.igeo.views.Snapper;
import org.deegree.igeo.views.swing.Footer;
import org.deegree.igeo.views.swing.drawingpanes.CreateLinestringDrawingPane;
import org.deegree.igeo.views.swing.drawingpanes.CreatePointDrawingPane;
import org.deegree.igeo.views.swing.drawingpanes.CreatePolygonDrawingPane;
import org.deegree.model.crs.CoordinateSystem;
import org.deegree.model.feature.Feature;
import org.deegree.model.feature.FeatureCollection;
import org.deegree.model.filterencoding.FilterEvaluationException;
import org.deegree.model.spatialschema.Curve;
import org.deegree.model.spatialschema.Envelope;
import org.deegree.model.spatialschema.EnvelopeImpl;
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.SurfacePatch;
/**
* Panel that will be used for drawing all digitizing operations like adding new geometries, moving vertices or selecting
* a geometry for removing. Because in deegree2 it is not so easy to draw specific features/geometries of a layers with
* a different style than the others this class implements several drawing methods for selected and newly digitized
* geometries. In future implementation this shall be removed to a central rendering module/engine.
*
* @author <a href="mailto:wanhoff@lat-lon.de">Jeronimo Wanhoff</a>
* @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
* @author last edited by: $Author$
*
* @version. $Revision$, $Date$
*/
public class DigitizerPanel extends JPanel {
private static final long serialVersionUID = 6043866783826397896L;
private static final ILogger LOG = LoggerFactory.getLogger( DigitizerPanel.class );
private static BasicStroke stroke = new BasicStroke( 2 );
private static BasicStroke simpleStroke = new BasicStroke( 1 );
protected DrawingPane drawingPane;
private IModule<Container> mapModule;
private DigitizerModule<?> ownerModule;
private MapModel mapModel;
private FeatureCollection selectedFC;
protected List<Geometry> geomList = null;
private MapTool<?> mapTool;
private boolean shallDrawSnapTargetVertices = false;
private BufferedImage buffer;
private DPKeyListener keyListener = new DPKeyListener();
private DPMouseMotionListener mouseMotionListener = new DPMouseMotionListener();
private DPMouseListener mouseListener = new DPMouseListener();
private JLabel footerLabel;
private Footer footer;
/**
*
* @param ownerModule
* @param mapModule
* @param assignedMapModel
*/
public DigitizerPanel( DigitizerModule<Container> ownerModule, IModule<Container> mapModule,
MapModel assignedMapModel ) {
this.ownerModule = ownerModule;
this.mapModule = mapModule;
this.mapModel = assignedMapModel;
this.mapModel.addChangeListener( new DPChangeListener() );
setDoubleBuffered( false );
geomList = new ArrayList<Geometry>();
this.mapTool = ( (DefaultMapModule<Container>) this.mapModule ).getMapTool();
setBackground( new Color( 255, 255, 255, 0 ) );
setBounds( 0, 0, assignedMapModel.getTargetDevice().getPixelWidth(),
assignedMapModel.getTargetDevice().getPixelHeight() );
setVisible( true );
footer = (Footer) ownerModule.getApplicationContainer().getFooter();
if ( footer != null ) {
footerLabel = new JLabel();
footerLabel.setPreferredSize( new Dimension( 300, 25 ) );
footerLabel.setBorder( BorderFactory.createMatteBorder( 0, 2, 0, 0, Color.BLACK ) );
}
}
/**
* resets a panel into its initial state and performs a repainting
*
*/
public void resetAll() {
resetGeometries();
resetDrawingPane();
resetSelectedFeatures();
invalidate();
repaint();
if ( getParent() != null ) {
getParent().repaint();
}
}
/**
* resets list of geometries
*
*/
public void resetGeometries() {
geomList.clear();
}
/**
* resets list of selected features
*
*/
public void resetSelectedFeatures() {
selectedFC = null;
}
/**
* resets the current drawing pane by setting it th <code>null</code>
*
*/
public void resetDrawingPane() {
drawingPane = null;
}
/**
*
* @return list of digitized objects
*/
public List<Geometry> getDigitizedPoints() {
return geomList;
}
@Override
public void repaint() {
// do not invoke super.repaint()!!!!!
if ( this.mapModel != null ) {
int w = this.mapModel.getTargetDevice().getPixelWidth();
int h = this.mapModel.getTargetDevice().getPixelHeight();
if ( w > 0 && h > 0 ) {
buffer = new BufferedImage( w, h, BufferedImage.TYPE_INT_ARGB );
Graphics g = buffer.getGraphics();
if ( shallDrawSnapTargetVertices ) {
drawSnapTargetVertices( g );
}
g.dispose();
}
}
}
@Override
public void paint( Graphics g ) {
super.paint( g );
if ( drawingPane != null ) {
if ( drawingPane.isDrawing() ) {
drawingPane.draw( drawingPane.getCurrent().x, drawingPane.getCurrent().y, g );
}
if ( mapTool.getState() instanceof EditState ) {
drawDigitizedGeoms( g );
}
}
g.drawImage( buffer, 0, 0, null );
}
/**
* sets the features that are currently selected
*
* @param fc
*/
public void setSelectedFeatures( FeatureCollection fc ) {
this.selectedFC = fc;
invalidate();
if ( getParent() != null ) {
getParent().repaint();
}
}
/**
*
* @return currently selected features
*/
public FeatureCollection getSelectedFeatures() {
return this.selectedFC;
}
/**
*
* @param width
* in map units
*/
@SuppressWarnings("unchecked")
private void setLineWidth() {
ApplicationContainer<Container> appCont = (ApplicationContainer<Container>) ownerModule.getApplicationContainer();
DigitizingLinesOpt dlo = appCont.getSettings().getDigitizingLinesOptions();
String s = dlo.getUOM();
float width = (float) dlo.getValue();
if ( !"pixel".equalsIgnoreCase( s ) ) {
// calculate pixel line width from geogr. line width
float w = mapModel.getTargetDevice().getPixelWidth();
float d = w / (float) mapModel.getEnvelope().getWidth();
width = d * width;
}
stroke = new BasicStroke( width );
if ( drawingPane != null && drawingPane instanceof CreateLinestringDrawingPane ) {
// just if current drawing pane is an instance of CreateLinestringDrawingPane
// the width of digitizing line can be set
// Notice that this method receives width measured in units of the CRS of the
// current map while the setLineWidth method of CreateLinestringDrawingPane
// expects width in pixel units
( (CreateLinestringDrawingPane) drawingPane ).setLineWidth( width );
}
}
// ////////////////////////////////////////////////////////////////////////////////
// the following drawing methods are a kind of workaround because in deegree2
// it is not so easy to draw specific features/geometries of a layers with
// a different style than the others
// ///////////////////////////////////////////////////////////////////////////////
private void drawDigitizedGeoms( Graphics g ) {
if ( drawingPane instanceof CreatePointDrawingPane ) {
GeoTransform gt = mapModel.getToTargetDeviceTransformation();
for ( int i = 0; i < geomList.size(); i++ ) {
Point p = (Point) geomList.get( i );
drawPoint( g, gt, p );
}
} else if ( drawingPane instanceof CreateLinestringDrawingPane ) {
for ( int i = 0; i < geomList.size(); i++ ) {
GeneralPath path = createPath( (Curve) geomList.get( i ) );
( (Graphics2D) g ).setStroke( stroke );
g.setColor( new Color( 1f, 0f, 0f ) );
( (Graphics2D) g ).draw( path );
}
} else if ( drawingPane instanceof CreatePolygonDrawingPane ) {
for ( int i = 0; i < geomList.size(); i++ ) {
GeneralPath path = createPath( (Surface) geomList.get( i ) );
g.setColor( new Color( 1f, 1f, 1f, 0.6f ) );
( (Graphics2D) g ).fill( path );
g.setColor( new Color( 1f, 0f, 0f ) );
( (Graphics2D) g ).draw( path );
}
}
}
private void drawSnapTargetVertices( Graphics g ) {
GeoTransform gt = mapModel.getToTargetDeviceTransformation();
List<Layer> layers = mapModel.getLayersSelectedForAction( MapModel.SELECTION_EDITING );
for ( Layer layer : layers ) {
List<DataAccessAdapter> tmp = layer.getDataAccess();
for ( DataAccessAdapter adapter : tmp ) {
if ( adapter instanceof FeatureAdapter ) {
FeatureCollection fc = null;
try {
fc = ( (FeatureAdapter) adapter ).getFeatureCollection( mapModel.getEnvelope() );
Iterator<Feature> iterator = fc.iterator();
while ( iterator.hasNext() ) {
drawFeature( g, gt, iterator.next() );
}
} catch ( FilterEvaluationException e ) {
e.printStackTrace();
}
}
}
}
}
private void drawFeature( Graphics g, GeoTransform gt, Feature feature ) {
Geometry[] geometries = feature.getGeometryPropertyValues();
for ( Geometry geometry : geometries ) {
// save current stroke
Stroke temp = ( (Graphics2D) g ).getStroke();
if ( geometry instanceof Point ) {
Point p = (Point) geometry;
drawPoint( g, gt, p );
} else if ( geometry instanceof MultiPoint ) {
Point[] points = ( (MultiPoint) geometry ).getAllPoints();
for ( Point point : points ) {
drawPoint( g, gt, point );
}
} else if ( geometry instanceof Curve ) {
drawCurve( g, (Curve) geometry, simpleStroke );
} else if ( geometry instanceof MultiCurve ) {
Curve[] curves = ( (MultiCurve) geometry ).getAllCurves();
for ( Curve curve : curves ) {
drawCurve( g, curve, simpleStroke );
}
} else if ( geometry instanceof Surface ) {
drawSurface( g, (Surface) geometry );
} else if ( geometry instanceof MultiSurface ) {
Surface[] surfaces = ( (MultiSurface) geometry ).getAllSurfaces();
for ( Surface surface : surfaces ) {
drawSurface( g, surface );
}
}
// restore stroke
( (Graphics2D) g ).setStroke( temp );
}
}
private void drawPoint( Graphics g, GeoTransform gt, Point p ) {
int xx = (int) Math.round( gt.getDestX( p.getX() ) );
int yy = (int) Math.round( gt.getDestY( p.getY() ) );
int radius = 3;
g.setColor( new Color( 1f, 1f, 1f, 0.6f ) );
g.fillOval( xx - radius, yy - radius, 2 * radius, 2 * radius );
g.setColor( new Color( 1f, 0f, 0f ) );
g.drawOval( xx - radius, yy - radius, 2 * radius, 2 * radius );
}
private void drawSurface( Graphics g, Surface surface ) {
GeneralPath path = createPath( surface );
g.setColor( new Color( 1f, 1f, 1f, 0.6f ) );
( (Graphics2D) g ).fill( path );
g.setColor( new Color( 0f, 0f, 1f ) );
( (Graphics2D) g ).draw( path );
drawVertices( g, path );
}
private void drawCurve( Graphics g, Curve curve, Stroke stroke ) {
GeneralPath path = createPath( curve );
( (Graphics2D) g ).setStroke( stroke );
g.setColor( new Color( 1f, 0f, 0f ) );
( (Graphics2D) g ).draw( path );
drawVertices( g, path );
}
private void drawVertices( Graphics g, GeneralPath path ) {
PathIterator pi = path.getPathIterator( null );
float[] coords = new float[2];
while ( !pi.isDone() ) {
pi.currentSegment( coords );
pi.next();
g.setColor( new Color( 1f, 1f, 0f ) );
g.fillOval( (int) coords[0] - 3, (int) coords[1] - 3, 7, 7 );
g.setColor( new Color( 0f, 0f, 0f ) );
g.drawOval( (int) coords[0] - 3, (int) coords[1] - 3, 7, 7 );
}
}
private GeneralPath createPath( Curve geom ) {
GeoTransform gt = mapModel.getToTargetDeviceTransformation();
GeneralPath path = new GeneralPath();
Position[] pos = null;
try {
pos = geom.getAsLineString().getPositions();
} catch ( GeometryException e ) {
// TODO
LOG.logError( e.getMessage(), e );
return path;
}
float xx = (float) gt.getDestX( pos[0].getX() );
float yy = (float) gt.getDestY( pos[0].getY() );
path.moveTo( xx, yy );
for ( int i = 1; i < pos.length; i++ ) {
float xx_ = (float) gt.getDestX( pos[i].getX() );
float yy_ = (float) gt.getDestY( pos[i].getY() );
if ( GeometryUtils.distance( xx, yy, xx_, yy_ ) > 2 || i == pos.length - 1 ) {
path.lineTo( xx_, yy_ );
xx = xx_;
yy = yy_;
}
}
return path;
}
private GeneralPath createPath( Surface surface ) {
GeneralPath path = new GeneralPath();
SurfacePatch patch = null;
try {
patch = surface.getSurfacePatchAt( 0 );
} catch ( GeometryException e ) {
LOG.logError( e.getMessage(), e );
}
if ( patch == null ) {
return null;
}
appendRingToPath( path, patch.getExteriorRing() );
Position[][] inner = patch.getInteriorRings();
if ( inner != null ) {
for ( int i = 0; i < inner.length; i++ ) {
appendRingToPath( path, inner[i] );
}
}
return path;
}
private void appendRingToPath( GeneralPath path, Position[] ring ) {
GeoTransform gt = mapModel.getToTargetDeviceTransformation();
if ( ring.length == 0 ) {
return;
}
Position p = gt.getDestPoint( ring[0] );
float xx = (float) p.getX();
float yy = (float) p.getY();
path.moveTo( xx, yy );
for ( int i = 1; i < ring.length; i++ ) {
p = gt.getDestPoint( ring[i] );
float xx_ = (float) p.getX();
float yy_ = (float) p.getY();
if ( GeometryUtils.distance( xx, yy, xx_, yy_ ) > 2 || i == ring.length - 1 ) {
path.lineTo( xx_, yy_ );
xx = xx_;
yy = yy_;
}
}
}
/**
*
* @return KeyListener assigned to a DigitizerPanel
*/
public KeyListener getKeyListener() {
return keyListener;
}
/**
*
* @return MouseMotionListener assigned to a DigitizerPanel
*/
public MouseMotionListener getMouseMotionListener() {
return mouseMotionListener;
}
/**
*
* @return MouseMotionListener assigned to a DigitizerPanel
*/
public MouseListener getMouseListener() {
return mouseListener;
}
// ////////////////////////////////////////////////////////////////////////////////
// inner classes
// ////////////////////////////////////////////////////////////////////////////////
/**
*
*
*
* @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
* @author last edited by: $Author$
*
* @version. $Revision$, $Date$
*/
private class DPMouseListener extends MouseAdapter {
/*
* (non-Javadoc)
*
* @see java.awt.event.MouseListener#mousePressed(java.awt.event.MouseEvent)
*/
public void mousePressed( MouseEvent event ) {
if ( event.isPopupTrigger() ) {
return;
}
ToolState state = mapTool.getState();
if ( state instanceof EditState || state instanceof SelectState ) {
if ( event.getClickCount() == 2 && drawingPane != null && drawingPane.isDrawing() ) {
drawingPane.undrawLastPoint();
finishDigitizingAction( event );
} else {
getParent();
Graphics g = getGraphics();
if ( drawingPane == null ) {
// first click on digitizer pane (map) after selecting a digitizer function
initDrawingPane( state, g );
}
if ( drawingPane != null ) {
// depending on drawing state: start or stop drawing. Stop drawing
// means setting a new vertex for a line of polygon
if ( !drawingPane.isDrawing() ) {
( (GeoDrawingPane) drawingPane ).setMapModel( mapModel );
( (GeoDrawingPane) drawingPane ).setFeatureCollection( selectedFC );
// initial mouse click to start digitizing a new Object
drawingPane.startDrawing( event.getX(), event.getY() );
} else {
// draw line or polygon boundary
drawingPane.stopDrawing( event.getX(), event.getY() );
}
mapModule.update();
}
state.mousePressed( event );
if ( event.getClickCount() == 1 && drawingPane != null && state instanceof CreatePointFeatureState ) {
// handle digitizer functions that requires just one mouse click or
// creates an inner ring of a polygon
// create point
finishDigitizingAction( event );
}
}
}
}
private void initDrawingPane( ToolState state, Graphics g ) {
drawingPane = state.createDrawingPane( mapModule.getApplicationContainer().getViewPlatform(), g );
if ( drawingPane != null ) {
drawingPane.setSnapper( new Snapper( ownerModule.getApplicationContainer() ) );
}
setLineWidth();
if ( footer != null ) {
footer.add( footerLabel );
}
}
@SuppressWarnings("unchecked")
@Override
public void mouseExited( MouseEvent e ) {
if ( mapTool.getState() instanceof EditState && e.getModifiers() == MouseEvent.SHIFT_MASK ) {
int x = e.getX();
int y = e.getY();
int limit = 2;
int h = mapModel.getTargetDevice().getPixelHeight() - limit;
int w = mapModel.getTargetDevice().getPixelWidth() - limit;
ApplicationContainer<Container> appContainer = (ApplicationContainer<Container>) mapModel.getApplicationContainer();
float pan = 0.1f;
EnvelopeImpl tmp = (EnvelopeImpl) mapModel.getEnvelope();
Envelope env = (Envelope) tmp.clone();
if ( x < limit ) {
env = env.translate( env.getWidth() * -1 * pan, 0 );
} else if ( y < limit ) {
env = env.translate( 0, env.getHeight() * pan );
} else if ( x > w ) {
env = env.translate( env.getWidth() * pan, 0 );
} else if ( y > h ) {
env = env.translate( 0, env.getHeight() * -1 * pan );
}
ZoomCommand zc = new ZoomCommand( mapModel );
zc.setZoomBox( env, mapModel.getTargetDevice().getPixelWidth(),
mapModel.getTargetDevice().getPixelHeight() );
try {
appContainer.getCommandProcessor().executeSychronously( zc, true );
} catch ( Exception ex ) {
LOG.logError( ex.getMessage(), ex );
DialogFactory.openErrorDialog( appContainer.getViewPlatform(), DigitizerPanel.this,
Messages.getMessage( getLocale(), "$MD11253" ),
Messages.getMessage( getLocale(), "$MD11252", env ), ex );
}
}
}
/*
* (non-Javadoc)
*
* @see java.awt.event.MouseListener#mouseReleased(java.awt.event.MouseEvent)
*/
public void mouseReleased( MouseEvent event ) {
if ( !event.isPopupTrigger() ) {
if ( mapTool.getState() instanceof RectangleSelectState
|| mapTool.getState() instanceof EditState.MoveFeatureState
|| mapTool.getState() instanceof EditState.MoveVertexState
|| mapTool.getState() instanceof EditState.InsertVertexState
|| mapTool.getState() instanceof EditState.DeleteVertexState
|| mapTool.getState() instanceof EditState.CreateRectangleFeatureState
|| mapTool.getState() instanceof EditState.CreateCircleFeatureState ) {
if ( drawingPane != null && drawingPane.isDrawing() ) {
finishDigitizingAction( event );
}
} else if ( mapTool.getState() instanceof EditState.CreateFeatureState ) {
if ( drawingPane != null && drawingPane.isDrawing() ) {
// pressing shift key while digitizing removes least drawn
// point from the panel
if ( event.getModifiers() == KeyEvent.SHIFT_MASK ) {
drawingPane.undrawLastPoint();
}
mapModule.update();
}
} else if ( mapTool.getState() instanceof EditState.MergeVerticesState ) {
if ( drawingPane.isDrawingStopped() ) {
finishDigitizingAction( event );
} else {
drawingPane.stopDrawing( event.getX(), event.getY() );
}
}
}
}
private void finishDigitizingAction( MouseEvent event ) {
if ( footer != null ) {
footer.remove( footerLabel );
footer.repaint();
}
if ( drawingPane != null && drawingPane.isDrawing() ) {
// final mouse click to stop digitizing a new Object
drawingPane.stopDrawing( event.getX(), event.getY() );
List<Point> points = ( (GeoDrawingPane) drawingPane ).getDrawObjectsAsGeoPoints();
try {
geomList = createGeometry( points );
} catch ( Exception e ) {
DialogFactory.openErrorDialog( "Application", DigitizerPanel.this,
Messages.getMessage( getLocale(), "$MD11123",
StringTools.stackTraceToString( e ) ),
Messages.getMessage( getLocale(), "$MD11124" ), e );
LOG.logError( e.getMessage(), e );
mapTool.resetState();
ownerModule.resetFunctionSelect();
return;
}
drawingPane.finishDrawing();
// repaint map with updated geometry state
mapModule.update();
// inform owner module about finished action
ownerModule.mouseActionFinished( geomList, event.getModifiers() );
}
}
private List<Geometry> createGeometry( List<Point> points )
throws GeometryException {
if ( mapTool.getState() instanceof EditState.CreatePointFeatureState ) {
geomList.add( points.get( 0 ) );
} else if ( mapTool.getState() instanceof EditState.CreateCurveFeatureState ) {
Position[] pos = pointListToPositions( points );
CoordinateSystem crs = points.get( 0 ).getCoordinateSystem();
geomList.add( GeometryFactory.createCurve( pos, crs ) );
} else if ( mapTool.getState() instanceof EditState.CreatePolygonFeatureState ) {
createSurface( points );
} else if ( mapTool.getState() instanceof EditState.SplitFeatureState ) {
Position[] pos = pointListToPositions( points );
CoordinateSystem crs = points.get( 0 ).getCoordinateSystem();
geomList.clear();
geomList.add( GeometryFactory.createCurve( pos, crs ) );
} else {
geomList.addAll( points );
}
return geomList;
}
private void createSurface( List<Point> points )
throws GeometryException {
// close polygon
Point p = GeometryFactory.createPoint( points.get( 0 ).getX(), points.get( 0 ).getY(),
points.get( 0 ).getCoordinateSystem() );
points.add( p );
Position[] pos = pointListToPositions( points );
CoordinateSystem crs = points.get( 0 ).getCoordinateSystem();
Surface surface = GeometryFactory.createSurface( pos, null, null, crs );
for ( int i = 0; i < geomList.size(); i++ ) {
Ring ring = ( (Surface) geomList.get( i ) ).getSurfaceBoundary().getExteriorRing();
Surface t = GeometryFactory.createSurface( ring.getPositions(), null, null,
surface.getCoordinateSystem() );
if ( t.contains( surface ) ) {
// current surface is an inner ring of the i'th surface that has
// already been digitized
if ( GeometryUtils.isClockwise( surface ) ) {
// an inner ring must have a counter clock wise position order
surface = GeometryUtils.invertOrder( surface );
}
Position[] inner = surface.getSurfaceBoundary().getExteriorRing().getPositions();
Surface tmp = (Surface) geomList.get( i );
Position[] ext = tmp.getSurfaceBoundary().getExteriorRing().getPositions();
Ring[] in = tmp.getSurfaceBoundary().getInteriorRings();
Position[][] interior = null;
if ( in == null || in.length == 0 ) {
interior = new Position[1][];
interior[0] = inner;
} else {
interior = new Position[in.length + 1][];
for ( int j = 0; j < in.length; j++ ) {
interior[j] = in[j].getPositions();
}
interior[interior.length - 1] = inner;
}
geomList.set( i, GeometryFactory.createSurface( ext, interior, null, tmp.getCoordinateSystem() ) );
return;
}
}
// current surface is not an inner ring!
geomList.add( GeometryUtils.ensureClockwise( surface ) );
}
/**
*
* @param pointList
* @return array of {@link Position}s
*/
private Position[] pointListToPositions( List<Point> pointList ) {
List<Position> pos = new ArrayList<Position>( pointList.size() );
Position p = null;
for ( int i = 0; i < pointList.size(); i++ ) {
p = pointList.get( i ).getPosition();
if ( i == 0 ) {
pos.add( p );
} else {
if ( !pos.get( pos.size() - 1 ).equals( p ) ) {
pos.add( p );
}
}
}
return pos.toArray( new Position[pos.size()] );
}
}
/**
*
*
*
* @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
* @author last edited by: $Author$
*
* @version. $Revision$, $Date$
*/
private class DPMouseMotionListener implements MouseMotionListener {
/*
* (non-Javadoc)
*
* @see java.awt.event.MouseMotionListener#mouseDragged(java.awt.event.MouseEvent)
*/
public void mouseDragged( MouseEvent event ) {
mapTool.getState().mouseDragged( event );
if ( mapTool.getState() instanceof EditState.CreateRectangleFeatureState
|| mapTool.getState() instanceof EditState.CreateCircleFeatureState
|| mapTool.getState() instanceof SelectState.RectangleSelectState
|| mapTool.getState() instanceof EditState.MoveFeatureState
|| mapTool.getState() instanceof EditState.MoveVertexState
|| mapTool.getState() instanceof EditState.InsertVertexState
|| mapTool.getState() instanceof EditState.MergeVerticesState ) {
if ( drawingPane != null && drawingPane.isDrawing() ) {
// just RectangleSelectState uses mouse dragging
drawingPane.draw( event.getX(), event.getY() );
mapModule.update();
}
}
}
/*
* (non-Javadoc)
*
* @see java.awt.event.MouseMotionListener#mouseMoved(java.awt.event.MouseEvent)
*/
public void mouseMoved( MouseEvent event ) {
if ( drawingPane != null && drawingPane.isDrawing() ) {
mapTool.getState().mouseMoved( event );
if ( mapTool.getState() instanceof EditState.CreateFeatureState
|| ( mapTool.getState() instanceof EditState.MergeVerticesState && drawingPane.isDrawingStopped() )
|| mapTool.getState() instanceof EditState.SplitFeatureState
|| mapTool.getState() instanceof EditState.JoinCurvesState ) {
drawingPane.draw( event.getX(), event.getY() );
mapModule.update();
}
}
}
}
/**
*
*
*
* @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
* @author last edited by: $Author$
*
* @version. $Revision$, $Date$
*/
public class DPKeyListener extends KeyAdapter {
/*
* (non-Javadoc)
*
* @see java.awt.event.KeyListener#keyPressed(java.awt.event.KeyEvent)
*/
public void keyPressed( KeyEvent event ) {
if ( event.getKeyCode() == KeyEvent.VK_M ) {
shallDrawSnapTargetVertices = !shallDrawSnapTargetVertices;
repaint();
if ( getParent() != null ) {
getParent().repaint();
}
}
}
}
/**
*
*
*
* @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
* @author last edited by: $Author$
*
* @version. $Revision$, $Date$
*/
private class DPChangeListener implements ChangeListener {
/*
* (non-Javadoc)
*
* @see org.deegree.igeo.ChangeListener#valueChanged(org.deegree.igeo.ValueChangedEvent)
*/
public void valueChanged( ValueChangedEvent event ) {
invalidate();
repaint();
}
}
}