001: /*
002: * The Unified Mapping Platform (JUMP) is an extensible, interactive GUI
003: * for visualizing and manipulating spatial features with geometry and attributes.
004: *
005: * JUMP is Copyright (C) 2003 Vivid Solutions
006: *
007: * This program implements extensions to JUMP and is
008: * Copyright (C) 2004 Integrated Systems Analysts, Inc.
009: *
010: * This program is free software; you can redistribute it and/or
011: * modify it under the terms of the GNU General Public License
012: * as published by the Free Software Foundation; either version 2
013: * of the License, or (at your option) any later version.
014: *
015: * This program is distributed in the hope that it will be useful,
016: * but WITHOUT ANY WARRANTY; without even the implied warranty of
017: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
018: * GNU General Public License for more details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with this program; if not, write to the Free Software
022: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
023: *
024: * For more information, contact:
025: *
026: * Integrated Systems Analysts, Inc.
027: * 630C Anchors St., Suite 101
028: * Fort Walton Beach, Florida
029: * USA
030: *
031: * (850)862-7321
032: */
033:
034: package org.openjump.core.ui.plugin.edittoolbox.cursortools;
035:
036: import java.awt.Cursor;
037: import java.awt.Shape;
038: import java.awt.event.MouseEvent;
039: import java.awt.geom.AffineTransform;
040: import java.awt.geom.NoninvertibleTransformException;
041: import java.awt.geom.Point2D;
042: import java.text.DecimalFormat;
043: import java.util.ArrayList;
044: import java.util.Collection;
045: import java.util.Iterator;
046:
047: import javax.swing.Icon;
048: import javax.swing.ImageIcon;
049:
050: import org.openjump.core.geomutils.GeoUtils;
051: import org.openjump.core.geomutils.MathVector;
052:
053: import com.vividsolutions.jts.geom.Coordinate;
054: import com.vividsolutions.jts.geom.CoordinateFilter;
055: import com.vividsolutions.jts.geom.Geometry;
056: import com.vividsolutions.jts.geom.GeometryFactory;
057: import com.vividsolutions.jump.I18N;
058: import com.vividsolutions.jump.workbench.model.Layer;
059: import com.vividsolutions.jump.workbench.plugin.EnableCheckFactory;
060: import com.vividsolutions.jump.workbench.ui.EditTransaction;
061: import com.vividsolutions.jump.workbench.ui.LayerViewPanel;
062: import com.vividsolutions.jump.workbench.ui.cursortool.DragTool;
063:
064: public class RotateSelectedItemTool extends DragTool {
065:
066: final static String rotateSelectedItem = I18N
067: .get("org.openjump.core.ui.plugin.edittoolbox.cursortools.RotateSelectedItemTool.Rotate-Selected-Item");
068: final static String angleST = I18N
069: .get("org.openjump.core.ui.plugin.edittoolbox.cursortools.angle");
070: final static String degrees = I18N
071: .get("org.openjump.core.ui.plugin.edittoolbox.cursortools.degrees");
072:
073: private EnableCheckFactory checkFactory;
074: private Shape selectedFeatureShape;
075: private Coordinate centerCoord;
076: protected boolean clockwise = true;
077: private double fullAngle = 0.0;
078: private boolean shiftDown = false;
079: private Cursor rotateCursor = createCursor(new ImageIcon(getClass()
080: .getResource("RotateSelCursor.gif")).getImage());;
081: private Cursor crosshairCursor = createCursor(new ImageIcon(
082: getClass().getResource("CrossHairCursor.gif")).getImage());
083:
084: public RotateSelectedItemTool(EnableCheckFactory checkFactory) {
085: this .checkFactory = checkFactory;
086: }
087:
088: public void activate(LayerViewPanel layerViewPanel) {
089: centerCoord = null;
090: super .activate(layerViewPanel);
091: }
092:
093: protected void gestureFinished() throws java.lang.Exception {
094: reportNothingToUndoYet();
095: if (!check(checkFactory
096: .createAtLeastNItemsMustBeSelectedCheck(1)))
097: return;
098: ArrayList transactions = new ArrayList();
099: for (Iterator i = getPanel().getSelectionManager()
100: .getLayersWithSelectedItems().iterator(); i.hasNext();) {
101: Layer layerWithSelectedItems = (Layer) i.next();
102: transactions.add(createTransaction(layerWithSelectedItems));
103: }
104: EditTransaction.commit(transactions);
105: }
106:
107: private EditTransaction createTransaction(Layer layer) {
108: EditTransaction transaction = EditTransaction
109: .createTransactionOnSelection(
110: new EditTransaction.SelectionEditor() {
111: public Geometry edit(
112: Geometry geometryWithSelectedItems,
113: Collection selectedItems) {
114: for (Iterator j = selectedItems
115: .iterator(); j.hasNext();) {
116: Geometry item = (Geometry) j.next();
117: rotate(item);
118: }
119: return geometryWithSelectedItems;
120: }
121: }, getPanel(), getPanel().getContext(),
122: getName(), layer, isRollingBackInvalidEdits(),
123: false);
124: return transaction;
125: }
126:
127: private void rotate(Geometry geometry) {
128: geometry.apply(new CoordinateFilter() {
129: public void filter(Coordinate coordinate) {
130: double cosAngle = Math.cos(fullAngle);
131: double sinAngle = Math.sin(fullAngle);
132: double x = coordinate.x - centerCoord.x;
133: double y = coordinate.y - centerCoord.y;
134: coordinate.x = centerCoord.x + (x * cosAngle)
135: + (y * sinAngle);
136: coordinate.y = centerCoord.y + (y * cosAngle)
137: - (x * sinAngle);
138: }
139: });
140: }
141:
142: public Cursor getCursor() {
143: if (shiftDown)
144: return crosshairCursor;
145: else
146: return rotateCursor;
147: }
148:
149: public Icon getIcon() {
150: return new ImageIcon(getClass().getResource("RotateSel.gif"));
151: }
152:
153: public void mouseMoved(MouseEvent e) {
154: if (e.isShiftDown()) {
155: shiftDown = true;
156: getPanel().setCursor(crosshairCursor);
157: } else {
158: shiftDown = false;
159: getPanel().setCursor(rotateCursor);
160: }
161: super .mouseMoved(e);
162: }
163:
164: public String getName() {
165: return rotateSelectedItem;
166: }
167:
168: public void mousePressed(MouseEvent e) {
169: try {
170: if (!check(checkFactory
171: .createSelectedItemsLayersMustBeEditableCheck())) {
172: return;
173: }
174:
175: if (e.isShiftDown()) {
176: centerCoord = getPanel().getViewport()
177: .toModelCoordinate(e.getPoint());
178: } else {
179: if (!check(checkFactory
180: .createAtLeastNItemsMustBeSelectedCheck(1)))
181: return;
182:
183: selectedFeatureShape = createSelectedItemsShape();
184: super .mousePressed(e);
185: }
186: } catch (Throwable t) {
187: getPanel().getContext().handleThrowable(t);
188: }
189: }
190:
191: private Shape createSelectedItemsShape()
192: throws NoninvertibleTransformException {
193: Collection selectedGeos = (getPanel().getSelectionManager()
194: .getSelectedItems());
195: Geometry geo = ((Geometry) selectedGeos.iterator().next());
196: Geometry[] allGeoms = new Geometry[selectedGeos.size()];
197: int i = 0;
198: for (Iterator j = selectedGeos.iterator(); j.hasNext();)
199: allGeoms[i++] = (Geometry) j.next();
200:
201: GeometryFactory geoFac = new GeometryFactory();
202: geo = geoFac.createGeometryCollection(allGeoms);
203:
204: if (centerCoord == null) {
205: centerCoord = geo.getCentroid().getCoordinate();
206: }
207: return getPanel().getJava2DConverter().toShape(geo);
208: }
209:
210: protected Shape getShape() throws Exception {
211: AffineTransform transform = new AffineTransform();
212: Point2D centerPt = getPanel().getViewport().toViewPoint(
213: new Point2D.Double(centerCoord.x, centerCoord.y));
214: Point2D initialPt = getViewSource();
215: Point2D currPt = getViewDestination();
216: MathVector center = new MathVector(centerPt.getX(), centerPt
217: .getY());
218: MathVector initial = new MathVector(initialPt.getX(), initialPt
219: .getY());
220: MathVector curr = new MathVector(currPt.getX(), currPt.getY());
221: MathVector initVec = initial.vectorBetween(center);
222: MathVector currVec = curr.vectorBetween(center);
223: double arcAngle = initVec.angleRad(currVec);
224: Coordinate initialCoord = getPanel().getViewport()
225: .toModelCoordinate(initialPt);
226: Coordinate currCoord = getPanel().getViewport()
227: .toModelCoordinate(currPt);
228:
229: boolean toRight = (GeoUtils.pointToRight(currCoord,
230: centerCoord, initialCoord));
231: boolean cwQuad = ((fullAngle >= 0.0) && (fullAngle <= 90.0) && clockwise);
232: boolean ccwQuad = ((fullAngle < 0.0) && (fullAngle >= -90.0) && !clockwise);
233:
234: if ((arcAngle <= 90.0) && (cwQuad || ccwQuad)) {
235: if (toRight)
236: clockwise = true;
237: else
238: clockwise = false;
239: }
240:
241: if ((fullAngle > 90.0) || (fullAngle < -90)) {
242: if ((clockwise && !toRight) || (!clockwise && toRight))
243: fullAngle = 360 - arcAngle;
244: else
245: fullAngle = arcAngle;
246: } else {
247: fullAngle = arcAngle;
248: }
249:
250: if (!clockwise)
251: fullAngle = -fullAngle;
252:
253: DecimalFormat df2 = new DecimalFormat("##0.0#");
254: getPanel().getContext().setStatusMessage(
255: angleST + ": " + df2.format(Math.toDegrees(fullAngle))
256: + " " + degrees);
257: // getPanel().getContext().setStatusMessage("angle = " + df2.format(Math.toDegrees(fullAngle)) + " degrees");
258: // getPanel().getContext().setStatusMessage("angle = " + getPanel().format(Math.toDegrees(fullAngle)) + " degrees");
259: transform.rotate(fullAngle, centerPt.getX(), centerPt.getY());
260: return transform.createTransformedShape(selectedFeatureShape);
261: }
262: }
|