/* ****************************************************************************** * Copyright (c) 2006-2012 XMind Ltd. and others. * * This file is a part of XMind 3. XMind releases 3 and * above are dual-licensed under the Eclipse Public License (EPL), * which is available at http://www.eclipse.org/legal/epl-v10.html * and the GNU Lesser General Public License (LGPL), * which is available at http://www.gnu.org/licenses/lgpl.html * See http://www.xmind.net/license.html for details. * * Contributors: * XMind Ltd. - initial API and implementation *******************************************************************************/ package org.xmind.gef.draw2d.geometry; import static java.lang.Math.abs; /** * @author Frank Shaka */ public class PrecisionRotator extends AbstractPrecisionTransformer { private static final PrecisionPoint P = new PrecisionPoint(); private static final PrecisionDimension D = new PrecisionDimension(); private static final PrecisionRectangle R = new PrecisionRectangle(); private double angle = 0; private double sin = 0d; private double cos = 1.0d; double cos2a = 1.0d; public PrecisionRotator() { } public PrecisionRotator(PrecisionPoint origin) { setOrigin(origin); } public double cos() { return cos; } /** * Returns the angle. * <ul> * <li>Represented in degrees;</li> * <li>0 degrees means horizontal rightwards;</li> * <li>Positive value means clock-wise.</li> * </ul> * * @return the angle */ public double getAngle() { return angle; } /** * Returns the angle. * <ul> * <li>Represented in degrees;</li> * <li>Zero degrees means horizontal rightwards;</li> * <li>Positive value means clock-wise.</li> * </ul> * * @param angle */ public void setAngle(double angle) { this.angle = angle; double rad = Math.toRadians(angle); sin = Math.sin(rad); cos = Math.cos(rad); cos2a = Math.cos(rad * 2); } public double sin() { return sin; } public PrecisionDimension t(PrecisionDimension d) { if (isEnabled()) { double width = tWidth(d.width, d.height); d.height = tHeight(d.width, d.height); d.width = width; } return d; } public double tWidth(double w, double h) { return abs(w * cos) + abs(h * sin); } public double tHeight(double w, double h) { return abs(w * sin) + abs(h * cos); } public PrecisionInsets t(PrecisionInsets i) { if (isEnabled()) { double x0 = getOrigin().x; double y0 = getOrigin().y; PrecisionRectangle r = t(R.setBounds(x0 - i.left, y0 - i.top, i .getWidth(), i.getHeight())); i.top = y0 - r.y; i.left = x0 - r.x; i.bottom = r.bottom() - y0; i.right = r.right() - x0; } return i; } public PrecisionPoint t(PrecisionPoint p) { if (isEnabled()) { double ox = getOrigin().x; double oy = getOrigin().y; double dx = p.x - ox; double dy = p.y - oy; p.x = ox + dx * cos - dy * sin; p.y = oy + dx * sin + dy * cos; } return p; } public PrecisionRectangle t(PrecisionRectangle r) { if (isEnabled()) { PrecisionPoint c = t(P.setLocation(r.x + r.width * 0.5d, r.y + r.height * 0.5d)); PrecisionDimension d = t(D.setSize(r.width, r.height)); r.x = c.x - d.width / 2; r.y = c.y - d.height / 2; r.width = d.width; r.height = d.height; } return r; } public PrecisionPolygon tPolygon(PrecisionRectangle r) { PrecisionPolygon polygon = PrecisionPolygon.createFromRect(r); for (int i = 0; i < polygon.size(); i++) { polygon.setPoint(t(polygon.getPoint(i)), i); } return polygon; } public PrecisionDimension r(PrecisionDimension d) { return r(d, -1, -1); } public PrecisionDimension r(PrecisionDimension d, double wHint, double hHint) { if (isEnabled()) { double w, h; if (cos2a == 0) { h = hHint; w = wHint; if (d.width == d.height) { double diag = abs(d.width / sin); if (hHint > 0 && wHint < 0) { w = diag - h; } else if (wHint > 0 && hHint < 0) { h = diag - w; } else if (wHint < 0 && hHint < 0) { w = h = diag / 2; } } } else { w = (d.width * abs(cos) - d.height * abs(sin)) / cos2a; h = (d.height * abs(cos) - d.width * abs(sin)) / cos2a; } d.width = w; d.height = h; } return d; } public PrecisionInsets r(PrecisionInsets i) { return r(i, -1, -1); } public PrecisionInsets r(PrecisionInsets i, double wHint, double hHint) { if (isEnabled()) { double ox = getOrigin().x; double oy = getOrigin().y; PrecisionRectangle r = r(R.setBounds(ox - i.left, oy - i.top, i .getWidth(), i.getHeight()), wHint, hHint); i.top = oy - r.y; i.left = ox - r.x; i.bottom = r.bottom() - oy; i.right = r.right() - ox; } return i; } public PrecisionPoint r(PrecisionPoint p) { if (isEnabled()) { double ox = getOrigin().x; double oy = getOrigin().y; double dx = p.x - ox; double dy = p.y - oy; p.x = ox + dx * cos + dy * sin; p.y = oy - dx * sin + dy * cos; } return p; } public PrecisionRectangle r(PrecisionRectangle r) { return r(r, -1, -1); } public PrecisionRectangle r(PrecisionRectangle r, double wHint, double hHint) { if (isEnabled()) { PrecisionPoint c = r(P.setLocation(r.x + r.width * 0.5d, r.y + r.height * 0.5d)); PrecisionDimension d = r(D.setSize(r.width, r.height), wHint, hHint); r.x = c.x - d.width / 2; r.y = c.y - d.height / 2; r.width = d.width; r.height = d.height; } return r; } public PrecisionPoint rp(PrecisionPoint p) { if (!isEnabled()) return new PrecisionPoint(p); setAngle(-getAngle()); PrecisionPoint p2 = tp(p); setAngle(-getAngle()); return p2; } }