Java tutorial
/*---------------- FILE HEADER KALYPSO ------------------------------------------ * * This file is part of kalypso. * Copyright (C) 2004 by: * * Technical University Hamburg-Harburg (TUHH) * Institute of River and coastal engineering * Denickestrae 22 * 21073 Hamburg, Germany * http://www.tuhh.de/wb * * and * * Bjoernsen Consulting Engineers (BCE) * Maria Trost 3 * 56070 Koblenz, Germany * http://www.bjoernsen.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: * * E-Mail: * belger@bjoernsen.de * schlienger@bjoernsen.de * v.doemming@tuhh.de * * ---------------------------------------------------------------------------*/ package org.kalypso.kalypsomodel1d2d.ui.map; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Cursor; import java.awt.Graphics; import java.awt.Point; import java.awt.Rectangle; import java.awt.event.KeyEvent; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import org.apache.commons.lang3.ArrayUtils; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.NullProgressMonitor; import org.kalypso.commons.command.ICommandTarget; import org.kalypso.contribs.eclipse.core.runtime.StatusUtilities; import org.kalypso.gml.processes.constDelaunay.ConstraintDelaunayHelper; import org.kalypso.kalypsomodel1d2d.KalypsoModel1D2DPlugin; import org.kalypso.kalypsomodel1d2d.schema.binding.discr.IFE1D2DElement; import org.kalypso.kalypsomodel1d2d.schema.binding.discr.IFE1D2DNode; import org.kalypso.kalypsomodel1d2d.schema.binding.discr.IFEDiscretisationModel1d2d; import org.kalypso.kalypsomodel1d2d.schema.binding.discr.IPolyElement; import org.kalypso.kalypsomodel1d2d.ui.i18n.Messages; import org.kalypso.kalypsomodel1d2d.ui.map.cmds.DeletePolyElementCmd; import org.kalypso.kalypsomodel1d2d.ui.map.element1d.Create2dElementCommand; import org.kalypso.kalypsomodel1d2d.ui.map.util.PointSnapper; import org.kalypso.kalypsomodel1d2d.ui.map.util.UtilMap; import org.kalypso.ogc.gml.IKalypsoFeatureTheme; import org.kalypso.ogc.gml.map.IMapPanel; import org.kalypso.ogc.gml.map.utilities.MapUtilities; import org.kalypso.ogc.gml.map.utilities.tooltip.ToolTipRenderer; import org.kalypso.ogc.gml.map.widgets.builders.IGeometryBuilder; import org.kalypso.ogc.gml.map.widgets.builders.LineGeometryBuilder; import org.kalypso.ogc.gml.map.widgets.builders.PolygonGeometryBuilder; import org.kalypso.ogc.gml.mapmodel.CommandableWorkspace; import org.kalypso.ogc.gml.mapmodel.IMapModell; import org.kalypso.ogc.gml.widgets.DeprecatedMouseWidget; import org.kalypsodeegree.graphics.displayelements.DisplayElement; import org.kalypsodeegree.graphics.sld.CssParameter; import org.kalypsodeegree.graphics.sld.LineSymbolizer; import org.kalypsodeegree.graphics.sld.Stroke; import org.kalypsodeegree.graphics.transformation.GeoTransform; import org.kalypsodeegree.model.geometry.GM_AbstractSurfacePatch; import org.kalypsodeegree.model.geometry.GM_Curve; import org.kalypsodeegree.model.geometry.GM_Envelope; import org.kalypsodeegree.model.geometry.GM_Exception; import org.kalypsodeegree.model.geometry.GM_MultiSurface; import org.kalypsodeegree.model.geometry.GM_Object; import org.kalypsodeegree.model.geometry.GM_Point; import org.kalypsodeegree.model.geometry.GM_Polygon; import org.kalypsodeegree.model.geometry.GM_PolygonPatch; import org.kalypsodeegree.model.geometry.GM_Position; import org.kalypsodeegree.model.geometry.GM_Triangle; import org.kalypsodeegree_impl.graphics.displayelements.DisplayElementFactory; import org.kalypsodeegree_impl.graphics.sld.LineSymbolizer_Impl; import org.kalypsodeegree_impl.graphics.sld.Stroke_Impl; import org.kalypsodeegree_impl.model.geometry.GeometryFactory; import org.kalypsodeegree_impl.tools.refinement.Refinement; /** * This widget is used in order to refine an existing 2D mesh by drawing a refinement line. The user gets a preview * before he starts the refinement of the model. * <ul> * <li>resulting elements with 5 corners are getting split into triangles by simple polygon triangulation * <li>arcs cannot be split twice * </ul> * * @author Thomas Jung */ public class RefineFEGeometryWidget extends DeprecatedMouseWidget { private boolean m_modePolygon = false; private Point m_currentMapPoint; private PointSnapper m_pointSnapper; private IGeometryBuilder m_geometryBuilder = null; private IKalypsoFeatureTheme m_theme; private IFEDiscretisationModel1d2d m_model1d2d; private final ToolTipRenderer m_toolTipRenderer = new ToolTipRenderer(); private final ToolTipRenderer m_warningRenderer = new ToolTipRenderer(); private GM_Object[] m_objects; private List<IPolyElement> m_featuresToRefine; private boolean m_warning; private GM_Object m_geom; public RefineFEGeometryWidget() { super(Messages.getString("org.kalypso.kalypsomodel1d2d.ui.map.RefineFEGeometryWidget.0"), //$NON-NLS-1$ Messages.getString("org.kalypso.kalypsomodel1d2d.ui.map.RefineFEGeometryWidget.1")); //$NON-NLS-1$ } @Override public void activate(final ICommandTarget commandPoster, final IMapPanel mapPanel) { super.activate(commandPoster, mapPanel); reinit(); } private final void reinit() { final IMapPanel mapPanel = getMapPanel(); final IMapModell mapModell = mapPanel.getMapModell(); mapPanel.repaintMap(); m_theme = UtilMap.findEditableTheme(mapPanel, IPolyElement.QNAME); m_model1d2d = UtilMap.findFEModelTheme(mapPanel); final String mode = m_modePolygon ? Messages.getString("RefineFEGeometryWidget.0") //$NON-NLS-1$ : Messages.getString("RefineFEGeometryWidget.1"); //$NON-NLS-1$ final String modeTooltip = String.format(Messages.getString("RefineFEGeometryWidget.2"), mode); //$NON-NLS-1$ m_toolTipRenderer.setBackgroundColor(new Color(1f, 1f, 0.6f, 0.70f)); m_toolTipRenderer.setTooltip( Messages.getString("org.kalypso.kalypsomodel1d2d.ui.map.RefineFEGeometryWidget.2") + modeTooltip); //$NON-NLS-1$ m_warningRenderer.setBackgroundColor(new Color(1f, 0.4f, 0.4f, 0.80f)); if (m_modePolygon) m_geometryBuilder = new PolygonGeometryBuilder(0, mapModell.getCoordinatesSystem()); else m_geometryBuilder = new LineGeometryBuilder(0, mapModell.getCoordinatesSystem()); m_pointSnapper = new PointSnapper(m_model1d2d, mapPanel); m_objects = null; } @Override public void leftPressed(final Point p) { m_warning = false; try { if (m_geometryBuilder == null) return; final IMapPanel mapPanel = getMapPanel(); final Object newNode = checkNewNode(p); if (newNode == null) mapPanel.setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR)); if (newNode instanceof IFE1D2DNode) { final GM_Point point = ((IFE1D2DNode) newNode).getPoint(); m_currentMapPoint = MapUtilities.retransform(getMapPanel(), point); m_geometryBuilder.addPoint(point); } else { m_currentMapPoint = p; m_geometryBuilder.addPoint(MapUtilities.transform(mapPanel, p)); } mapPanel.setCursor(Cursor.getDefaultCursor()); } catch (final Exception e) { e.printStackTrace(); final IStatus status = StatusUtilities.statusFromThrowable(e); KalypsoModel1D2DPlugin.getDefault().getLog().log(status); reinit(); } } @Override public void moved(final Point p) { final IMapPanel mapPanel = getMapPanel(); if (mapPanel == null) return; final Object newNode = checkNewNode(p); if (newNode instanceof IFE1D2DNode) { final IFE1D2DNode candidateNode = (IFE1D2DNode) newNode; m_currentMapPoint = MapUtilities.retransform(getMapPanel(), candidateNode.getPoint()); } else m_currentMapPoint = p; if (newNode == null) getMapPanel().setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR)); else getMapPanel().setCursor(Cursor.getDefaultCursor()); repaintMap(); } @Override public void paint(final Graphics g) { /* always paint a small rectangle of current position */ if (m_currentMapPoint == null) return; final int[][] posPoints = UtilMap.getPointArrays(m_currentMapPoint); final int[] arrayX = posPoints[0]; final int[] arrayY = posPoints[1]; /* Paint as linestring. */ g.drawPolygon(arrayX, arrayY, arrayX.length); UtilMap.drawHandles(g, arrayX, arrayY); /* paint the snap */ if (m_pointSnapper != null) m_pointSnapper.paint(g); super.paint(g); final IMapPanel mapPanel = getMapPanel(); final Rectangle bounds = mapPanel.getScreenBounds(); final GeoTransform projection = mapPanel.getProjection(); m_toolTipRenderer.paintToolTip(new Point(5, bounds.height - 5), g, bounds); if (m_warning == true) m_warningRenderer.paintToolTip(new Point(5, bounds.height - 80), g, bounds); if (m_geometryBuilder != null) m_geometryBuilder.paint(g, projection, m_currentMapPoint); try { if (!ArrayUtils.isEmpty(m_objects)) drawRefinement(g, projection); } catch (final Exception e) { e.printStackTrace(); } } private void drawRefinement(final Graphics g, final GeoTransform projection) throws CoreException, GM_Exception { /* Paint a rect. */ final LineSymbolizer symb = new LineSymbolizer_Impl(); final Stroke stroke = new Stroke_Impl(new HashMap<String, CssParameter>(), null, null); final Color color = new Color(255, 0, 0); for (final GM_Object object : m_objects) { if (object instanceof GM_Polygon) { final GM_Polygon surface = (GM_Polygon) object; final String crs = surface.getCoordinateSystem(); for (final GM_AbstractSurfacePatch surfacePatch : surface) { final GM_Position[] exteriorRing = surfacePatch.getExteriorRing(); final GM_Curve curve = org.kalypsodeegree_impl.model.geometry.GeometryFactory .createGM_Curve(exteriorRing, crs); stroke.setWidth(3); stroke.setLineCap(BasicStroke.CAP_ROUND); stroke.setLineJoin(BasicStroke.JOIN_ROUND); stroke.setStroke(color); symb.setStroke(stroke); final DisplayElement de = DisplayElementFactory.buildLineStringDisplayElement(null, curve, symb); de.paint(g, projection, new NullProgressMonitor()); } } } } @Override public void keyPressed(final KeyEvent e) { if (e.getKeyCode() == KeyEvent.VK_SPACE) { m_modePolygon = !m_modePolygon; reinit(); } else if (e.getKeyCode() == KeyEvent.VK_ESCAPE) reinit(); else if (e.getKeyCode() == KeyEvent.VK_BACK_SPACE) m_geometryBuilder.removeLastPoint(); else if (e.getKeyCode() == KeyEvent.VK_ENTER) convertRefinementToModel(); else super.keyPressed(e); } private void convertRefinementToModel() { if (m_objects == null) return; // first, we re-select all features that lie on the refined GM_Object's center points. // This is necessary because of some additional filters used in the refinement class. /* calculate centroids of refinements */ final List<GM_Point> centroidList = getCentroids(m_objects); /* reselect */ final List<IPolyElement> refineList = reselectFeatures(centroidList); try { final CommandableWorkspace workspace = m_theme.getWorkspace(); /* Initialize elements needed for edges and elements */ final IFEDiscretisationModel1d2d discModel = (IFEDiscretisationModel1d2d) workspace.getRootFeature(); // add remove element command final DeletePolyElementCmd deleteCommand = new DeletePolyElementCmd(discModel); for (final IPolyElement feature : refineList) { deleteCommand.addElementToRemove(feature); } try { workspace.postCommand(deleteCommand); } catch (final Exception e) { e.printStackTrace(); } // FIXME: use Add2DElementCommand instead?! /* create new elements */ for (final GM_Object object : m_objects) { if (object instanceof GM_Polygon) { final GM_Polygon surface = (GM_Polygon) object; final GM_Position[] poses = surface.getSurfacePatch().getExteriorRing(); final GM_Point[] points = new GM_Point[poses.length - 1]; for (int i = 0; i < poses.length - 1; i++) points[i] = org.kalypsodeegree_impl.model.geometry.GeometryFactory.createGM_Point(poses[i], surface.getCoordinateSystem()); final Create2dElementCommand createCommand = new Create2dElementCommand(discModel, points); workspace.postCommand(createCommand); } } reinit(); } catch (final Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } private List<IPolyElement> reselectFeatures(final List<GM_Point> centroidList) { final List<IPolyElement> refineList = new ArrayList<>(); for (final IPolyElement feature : m_featuresToRefine) { final GM_Polygon surface = feature.getGeometry(); for (final GM_Point centroid : centroidList) { if (surface.intersects(centroid)) refineList.add(feature); } } return refineList; } private List<GM_Point> getCentroids(final GM_Object[] objects) { final List<GM_Point> centroidList = new ArrayList<>(); for (final GM_Object object : objects) { if (object instanceof GM_Polygon) { final GM_Polygon surf = (GM_Polygon) object; final GM_Point centroid = surf.getCentroid(); centroidList.add(centroid); } } return centroidList; } @Override public void doubleClickedLeft(final Point p) { if (m_geometryBuilder == null) return; try { m_geom = m_geometryBuilder.finish(); finishGeometry(); } catch (final Exception e) { e.printStackTrace(); final IStatus status = StatusUtilities.statusFromThrowable(e); KalypsoModel1D2DPlugin.getDefault().getLog().log(status); final IMapPanel mapPanel = getMapPanel(); mapPanel.setMessage(Messages.getString("org.kalypso.kalypsomodel1d2d.ui.map.RefineFEGeometryWidget.4") //$NON-NLS-1$ + status.getMessage()); reinit(); } } protected void finishGeometry() throws GM_Exception { if (m_geom == null) return; m_warning = false; m_featuresToRefine = new ArrayList<>(); /* select features */ final String crs = m_geom.getCoordinateSystem(); final List<IPolyElement> selectedFeatures = doSelect(m_geom); final List<GM_Polygon> surfaceList = new ArrayList<>(); for (final IPolyElement feature : selectedFeatures) { // get the geometry final GM_Polygon surface = feature.getGeometry(); surfaceList.add(surface); // get the selected Feature m_featuresToRefine.add(feature); } /* REFINEMENT */ final GM_MultiSurface multiSurface = GeometryFactory .createGM_MultiSurface(surfaceList.toArray(new GM_Polygon[surfaceList.size()]), crs); final GM_MultiSurface[] multiSurfaces = new GM_MultiSurface[] { multiSurface }; final Refinement refinement = new Refinement(); final GM_Polygon[] refinements = refinement.doRefine(multiSurfaces, m_geom); final List<GM_Polygon> refinementList = new ArrayList<>(); for (final GM_Polygon surface : refinements) { final GM_PolygonPatch surfacePatch = surface.getSurfacePatch(); final GM_Polygon newSurface = GeometryFactory.createGM_Surface(surfacePatch); final GM_Triangle[] triangles = ConstraintDelaunayHelper.triangulateSimple(newSurface); for (final GM_Triangle triangle : triangles) refinementList.add(GeometryFactory.createGM_Surface(triangle)); } if (refinementList.size() == 0) { m_warning = true; m_warningRenderer .setTooltip(Messages.getString("org.kalypso.kalypsomodel1d2d.ui.map.RefineFEGeometryWidget.5")); //$NON-NLS-1$ } // create new GM_Objects m_objects = refinementList.toArray(new GM_Polygon[refinementList.size()]); m_geometryBuilder.reset(); getMapPanel().repaintMap(); } private List<IPolyElement> doSelect(final GM_Object selectGeometry) { if (selectGeometry == null) return null; // select feature from featureList by using the selectGeometry final List<IPolyElement> selectedFeatures = new ArrayList<>(); final List<IPolyElement> selectedSubList = selectFeatures(selectGeometry); if (selectedSubList != null) selectedFeatures.addAll(selectedSubList); return selectedFeatures; } private List<IPolyElement> selectFeatures(final GM_Object theGeom) { final List<IPolyElement> selectedFeatures = new ArrayList<>(); final GM_Envelope envelope = theGeom.getEnvelope(); final List<IFE1D2DElement> result = m_model1d2d.queryElements(envelope, null); for (final IFE1D2DElement element : result) { if (element instanceof IPolyElement) { final IPolyElement polyElement = (IPolyElement) element; final GM_Object geom = polyElement.getGeometry(); if (theGeom.intersects(geom)) selectedFeatures.add(polyElement); } } return selectedFeatures; } private Object checkNewNode(final Point p) { final IMapPanel mapPanel = getMapPanel(); if (mapPanel == null) return null; final GM_Point currentPoint = MapUtilities.transform(mapPanel, p); return m_pointSnapper == null ? null : m_pointSnapper.moved(currentPoint); } }