/* * This is part of Geomajas, a GIS framework, http://www.geomajas.org/. * * Copyright 2008-2015 Geosparc nv, http://www.geosparc.com/, Belgium. * * The program is available in open source according to the GNU Affero * General Public License. All contributions in this program are covered * by the Geomajas Contributors License Agreement. For full licensing * details, see LICENSE.txt in the project root. */ package org.geomajas.gwt2.plugin.editing.client.gfx; import org.geomajas.geometry.Coordinate; import org.geomajas.geometry.Geometry; import org.geomajas.geometry.service.GeometryService; import org.geomajas.gwt.client.map.RenderSpace; import org.geomajas.gwt2.client.GeomajasImpl; import org.geomajas.gwt2.client.gfx.GeometryPath; import org.geomajas.gwt2.client.map.MapPresenter; import org.geomajas.plugin.editing.client.service.GeometryEditService; import org.geomajas.plugin.editing.client.service.GeometryIndex; import org.geomajas.plugin.editing.client.service.GeometryIndexNotFoundException; import org.vaadin.gwtgraphics.client.Group; import org.vaadin.gwtgraphics.client.Shape; import org.vaadin.gwtgraphics.client.VectorObject; import org.vaadin.gwtgraphics.client.shape.Path; import org.vaadin.gwtgraphics.client.shape.Rectangle; import org.vaadin.gwtgraphics.client.shape.path.LineTo; import org.vaadin.gwtgraphics.client.shape.path.MoveTo; /** * Default implementation of the {@link GeometryIndexShapeFactory}. It will create a path for an edge, a path for a * geometry and a rectangle for a vertex. * * @author Pieter De Graef * @author Jan De Moerloose */ public class DefaultGeometryIndexShapeFactory implements GeometryIndexShapeFactory { private static final int VERTEX_SIZE = 12; private static final int VERTEX_HALF_SIZE = 6; private final MapPresenter mapPresenter; private final RenderSpace targetSpace; // ------------------------------------------------------------------------ // Constructor: // ------------------------------------------------------------------------ public DefaultGeometryIndexShapeFactory(MapPresenter mapPresenter, RenderSpace targetSpace) { this.mapPresenter = mapPresenter; this.targetSpace = targetSpace; } // ------------------------------------------------------------------------ // GeometryEditShapeFactory implementation: // ------------------------------------------------------------------------ @Override public VectorObject create(GeometryEditService editService, GeometryIndex index) throws GeometryIndexNotFoundException { if (index == null) { return createGeometry(editService, index); } switch (editService.getIndexService().getType(index)) { case TYPE_VERTEX: return createVertex(editService, index); case TYPE_EDGE: return createEdge(editService, index); default: return createGeometry(editService, index); } } @Override public void update(VectorObject shape, GeometryEditService editService, GeometryIndex index) throws GeometryIndexNotFoundException { if (index != null) { switch (editService.getIndexService().getType(index)) { case TYPE_VERTEX: updateVertex((Shape) shape, editService, index); break; case TYPE_EDGE: updateEdge((Shape) shape, editService, index); break; default: updateGeometry(shape, editService, index); } } else { updateGeometry(shape, editService, index); } } // ------------------------------------------------------------------------ // Private methods for creating shapes: // ------------------------------------------------------------------------ private Shape createVertex(GeometryEditService editService, GeometryIndex index) throws GeometryIndexNotFoundException { Geometry geometry = editService.getGeometry(); Coordinate v = editService.getIndexService().getVertex(geometry, index); if (!targetSpace.equals(RenderSpace.WORLD)) { v = mapPresenter.getViewPort().getTransformationService().transform(v, RenderSpace.WORLD, targetSpace); } return new Rectangle(v.getX() - VERTEX_HALF_SIZE, v.getY() - VERTEX_HALF_SIZE, VERTEX_SIZE, VERTEX_SIZE); } private Shape createEdge(GeometryEditService editService, GeometryIndex index) throws GeometryIndexNotFoundException { Geometry geometry = editService.getGeometry(); Coordinate[] e = editService.getIndexService().getEdge(geometry, index); if (!targetSpace.equals(RenderSpace.WORLD)) { e[0] = mapPresenter.getViewPort().getTransformationService() .transform(e[0], RenderSpace.WORLD, targetSpace); e[1] = mapPresenter.getViewPort().getTransformationService() .transform(e[1], RenderSpace.WORLD, targetSpace); } Path edge = new Path(e[0].getX(), e[0].getY()); edge.lineTo(e[1].getX(), e[1].getY()); return edge; } private VectorObject createGeometry(GeometryEditService editService, GeometryIndex index) throws GeometryIndexNotFoundException { Geometry geometry = editService.getGeometry(); if (index != null) { geometry = editService.getIndexService().getGeometry(geometry, index); } Geometry g = geometry; if (!targetSpace.equals(RenderSpace.WORLD)) { g = mapPresenter.getViewPort().getTransformationService().transform(g, RenderSpace.WORLD, targetSpace); } return GeomajasImpl.getInstance().getGfxUtil().toShape(g); } // ------------------------------------------------------------------------ // Private methods for updating shapes: // ------------------------------------------------------------------------ private void updateVertex(Shape shape, GeometryEditService editService, GeometryIndex index) throws GeometryIndexNotFoundException { if (shape instanceof Rectangle) { Rectangle rectangle = (Rectangle) shape; Geometry geometry = editService.getGeometry(); Coordinate v = editService.getIndexService().getVertex(geometry, index); if (!targetSpace.equals(RenderSpace.WORLD)) { v = mapPresenter.getViewPort().getTransformationService().transform(v, RenderSpace.WORLD, targetSpace); } rectangle.setUserX(v.getX() - VERTEX_HALF_SIZE); rectangle.setUserY(v.getY() - VERTEX_HALF_SIZE); } } private void updateEdge(Shape shape, GeometryEditService editService, GeometryIndex index) throws GeometryIndexNotFoundException { if (shape instanceof Path) { Path path = (Path) shape; Geometry geometry = editService.getGeometry(); Coordinate[] edge = editService.getIndexService().getEdge(geometry, index); if (!targetSpace.equals(RenderSpace.WORLD)) { edge[0] = mapPresenter.getViewPort().getTransformationService() .transform(edge[0], RenderSpace.WORLD, targetSpace); edge[1] = mapPresenter.getViewPort().getTransformationService() .transform(edge[1], RenderSpace.WORLD, targetSpace); } path.setStep(0, new MoveTo(false, edge[0].getX(), edge[0].getY())); path.setStep(1, new LineTo(false, edge[1].getX(), edge[1].getY())); } } private void updateGeometry(VectorObject object, GeometryEditService editService, GeometryIndex index) throws GeometryIndexNotFoundException { Geometry geometry = editService.getGeometry(); if (index != null) { geometry = editService.getIndexService().getGeometry(geometry, index); } Geometry g = geometry; if (!targetSpace.equals(RenderSpace.WORLD)) { g = mapPresenter.getViewPort().getTransformationService().transform(g, RenderSpace.WORLD, targetSpace); } if (object instanceof GeometryPath) { GeometryPath path = (GeometryPath) object; path.setGeometry(g); } else if (object instanceof Shape) { // point case, update the position Shape point = (Shape) object; Coordinate c = GeometryService.getCentroid(g); point.setUserX(c.getX()); point.setUserY(c.getY()); } else if (object instanceof Group) { // group, replace the children (multipoint case) Group group = (Group) object; group.clear(); Group newGroup = (Group) GeomajasImpl.getInstance().getGfxUtil().toShape(g); for (int i = 0; i < newGroup.getVectorObjectCount(); i++) { VectorObject child = group.getVectorObject(i); newGroup.remove(child); group.add(child); } } } }