/* * 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.plugin.editing.client.operation; import org.geomajas.geometry.Coordinate; import org.geomajas.geometry.Geometry; import org.geomajas.plugin.editing.client.service.GeometryEditService; import org.geomajas.plugin.editing.client.service.GeometryEditState; import org.geomajas.plugin.editing.client.service.GeometryIndex; import org.geomajas.plugin.editing.client.service.GeometryIndexNotFoundException; import org.geomajas.plugin.editing.client.service.GeometryIndexService; import org.geomajas.plugin.editing.client.service.GeometryIndexType; /** * Geometry index operation that deletes a single vertex at the given index. This implementation does not create a new * geometry instance, but changes the given geometry. * * @author Pieter De Graef */ public class DeleteVertexOperation implements GeometryIndexOperation { private final GeometryIndexService service; private final GeometryEditService geometryEditService; private GeometryIndex index; private Coordinate coordinate; private Coordinate tentativeMoveOrigin; /** * Initialize this operation with an indexing service. * * @param service * geometry index service. */ public DeleteVertexOperation(GeometryIndexService service, GeometryEditService geometryEditService) { this.service = service; this.geometryEditService = geometryEditService; } @Override public Geometry execute(Geometry geometry, GeometryIndex index) throws GeometryOperationFailedException { this.index = index; if (service.getType(index) != GeometryIndexType.TYPE_VERTEX) { throw new GeometryOperationFailedException("Index of wrong type. Must be TYPE_VERTEX."); } try { coordinate = service.getVertex(geometry, index); tentativeMoveOrigin = null; delete(geometry, index); updateGeometryEditServiceProperties(geometry); return geometry; } catch (GeometryIndexNotFoundException e) { throw new GeometryOperationFailedException(e); } } @Override public GeometryIndexOperation getInverseOperation() { return new InsertVertexOperation(service, coordinate, geometryEditService); } @Override public GeometryIndex getGeometryIndex() { return index; } // ------------------------------------------------------------------------ // Private methods: // ------------------------------------------------------------------------ private void delete(Geometry geom, GeometryIndex index) throws GeometryIndexNotFoundException { if (index.hasChild() && geom.getGeometries() != null && geom.getGeometries().length > index.getValue()) { delete(geom.getGeometries()[index.getValue()], index.getChild()); } else if (index.getType() == GeometryIndexType.TYPE_VERTEX) { deleteVertex(geom, index); } else { throw new GeometryIndexNotFoundException("Could not match index with given geometry"); } } private void deleteVertex(Geometry geom, GeometryIndex index) throws GeometryIndexNotFoundException { if (Geometry.POINT.equals(geom.getGeometryType())) { if (geom.getCoordinates() != null && geom.getCoordinates().length == 1) { geom.setCoordinates(null); } else { throw new GeometryIndexNotFoundException("Vertex index out of bounds."); } } else if (Geometry.LINE_STRING.equals(geom.getGeometryType())) { if (index.getValue() < 0 || geom.getCoordinates() == null || geom.getCoordinates().length == 0 || geom.getCoordinates().length <= index.getValue()) { throw new GeometryIndexNotFoundException("Vertex index out of bounds."); } if (geom.getCoordinates().length == 1) { geom.setCoordinates(null); } else { Coordinate[] result = new Coordinate[geom.getCoordinates().length - 1]; int count = 0; for (int i = 0; i < geom.getCoordinates().length; i++) { if (i != index.getValue()) { result[count] = geom.getCoordinates()[i]; count++; } } geom.setCoordinates(result); tentativeMoveOrigin = result[result.length - 1]; } } else if (Geometry.LINEAR_RING.equals(geom.getGeometryType())) { if (index.getValue() < 0 || geom.getCoordinates() == null || geom.getCoordinates().length == 0 || (geom.getCoordinates().length - 1) <= index.getValue()) { throw new GeometryIndexNotFoundException("Vertex index out of bounds."); } if (geom.getCoordinates().length == 2) { geom.setCoordinates(null); } else { Coordinate[] result = new Coordinate[geom.getCoordinates().length - 1]; int count = 0; for (int i = 0; i < geom.getCoordinates().length; i++) { if (i != index.getValue()) { result[count] = geom.getCoordinates()[i]; count++; } } result[result.length - 1] = new Coordinate(result[0]); geom.setCoordinates(result); tentativeMoveOrigin = result[result.length - 2]; } } else { throw new GeometryIndexNotFoundException("Could not match index with given geometry"); } } private void updateGeometryEditServiceProperties(Geometry geometry) { if (geometryEditService.getEditingState().equals(GeometryEditState.INSERTING)) { if (geometry.getGeometryType().equals(Geometry.POINT) || geometry.getGeometryType().equals(Geometry.MULTI_POINT)) { tentativeMoveOrigin = null; // to make sure; should be null already } geometryEditService.setTentativeMoveOrigin(tentativeMoveOrigin); geometryEditService.setInsertIndex(getGeometryIndex()); } } }