/*FreeMind - A Program for creating and viewing Mindmaps *Copyright (C) 2000-2006 Joerg Mueller, Daniel Polansky, Christian Foltin, Dimitri Polivaev and others. * *See COPYING for Details * *This program is free software; you can redistribute it and/or *modify it under the terms of the GNU General Public License *as published by the Free Software Foundation; either version 2 *of the License, or (at your option) any later version. * *This program 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 General Public License for more details. * *You should have received a copy of the GNU General Public License *along with this program; if not, write to the Free Software *Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* * Created on 16.05.2004 * * To change the template for this generated file go to * Window>Preferences>Java>Code Generation>Code and Comments */ package freemind.view.mindmapview; import java.awt.Shape; import java.awt.geom.PathIterator; import java.awt.geom.QuadCurve2D; import java.awt.geom.Rectangle2D; class PathBBox { public static Rectangle2D getBBox(Shape s) { boolean first = true; double bounds[] = new double[4]; double coords[] = new double[6]; double curx = 0; double cury = 0; double movx = 0; double movy = 0; double cpx0, cpy0, cpx1, cpy1, endx, endy; for (PathIterator pi = s.getPathIterator(null); !pi.isDone(); pi.next()) { int type = pi.currentSegment(coords); switch (pi.currentSegment(coords)) { case PathIterator.SEG_MOVETO: movx = curx = coords[0]; movy = cury = coords[1]; if (first) { bounds[0] = bounds[2] = curx; bounds[1] = bounds[3] = cury; first = false; } else { accum(bounds, curx, cury); } break; case PathIterator.SEG_LINETO: curx = coords[0]; cury = coords[1]; accum(bounds, curx, cury); break; case PathIterator.SEG_QUADTO: cpx0 = coords[0]; cpy0 = coords[1]; endx = coords[2]; endy = coords[3]; double t = findQuadZero(curx, cpx0, endx); if (t > 0 && t < 1) { accumQuad(bounds, t, curx, cury, cpx0, cpy0, endx, endy); } t = findQuadZero(cury, cpy0, endy); if (t > 0 && t < 1) { accumQuad(bounds, t, curx, cury, cpx0, cpy0, endx, endy); } curx = endx; cury = endy; accum(bounds, curx, cury); break; case PathIterator.SEG_CUBICTO: cpx0 = coords[0]; cpy0 = coords[1]; cpx1 = coords[2]; cpy1 = coords[3]; endx = coords[4]; endy = coords[5]; int num = findCubicZeros(coords, curx, cpx0, cpx1, endx); for (int i = 0; i < num; i++) { accumCubic(bounds, coords[i], curx, cury, cpx0, cpy0, cpx1, cpy1, endx, endy); } num = findCubicZeros(coords, cury, cpy0, cpy1, endy); for (int i = 0; i < num; i++) { accumCubic(bounds, coords[i], curx, cury, cpx0, cpy0, cpx1, cpy1, endx, endy); } curx = endx; cury = endy; accum(bounds, curx, cury); break; case PathIterator.SEG_CLOSE: // Original starting point already included curx = movx; cury = movy; break; } } return new Rectangle2D.Double(bounds[0], bounds[1], bounds[2] - bounds[0], bounds[3] - bounds[1]); } private static void accum(double[] bounds, double x, double y) { bounds[0] = Math.min(bounds[0], x); bounds[1] = Math.min(bounds[1], y); bounds[2] = Math.max(bounds[2], x); bounds[3] = Math.max(bounds[3], y); } private static double findQuadZero(double cur, double cp, double end) { // The polynomial form of the Quadratic is: // eqn[0] = cur; // eqn[1] = cp + cp - cur - cur; // eqn[2] = cur - cp - cp + end; // Since we want the derivative, we can calculate it in one step: // deriv[0] = cp + cp - cur - cur; // deriv[1] = 2 * (cur - cp - cp + end); // Since we really want the zero, we can calculate that in one step: // zero = -deriv[0] / deriv[1] return -(cp + cp - cur - cur) / (2.0 * (cur - cp - cp + end)); } private static void accumQuad(double bounds[], double t, double curx, double cury, double cpx0, double cpy0, double endx, double endy) { double u = (1 - t); double x = curx * u * u + 2.0 * cpx0 * t * u + endx * t * t; double y = cury * u * u + 2.0 * cpy0 * t * u + endy * t * t; accum(bounds, x, y); } private static int findCubicZeros(double zeros[], double cur, double cp0, double cp1, double end) { // The polynomial form of the Cubic is: // eqn[0] = cur; // eqn[1] = (cp0 - cur) * 3.0; // eqn[2] = (cp1 - cp0 - cp0 + cur) * 3.0; // eqn[3] = end + (cp0 - cp1) * 3.0 - cur; // Since we want the derivative, we can calculate it in one step: zeros[0] = (cp0 - cur) * 3.0; zeros[1] = (cp1 - cp0 - cp0 + cur) * 6.0; zeros[2] = (end + (cp0 - cp1) * 3.0 - cur) * 3.0; int num = QuadCurve2D.solveQuadratic(zeros); int ret = 0; for (int i = 0; i < num; i++) { double t = zeros[i]; if (t > 0 && t < 1) { zeros[ret] = t; ret++; } } return ret; } private static void accumCubic(double bounds[], double t, double curx, double cury, double cpx0, double cpy0, double cpx1, double cpy1, double endx, double endy) { double u = (1 - t); double x = curx * u * u * u + 3.0 * cpx0 * t * u * u + 3.0 * cpx1 * t * t * u + endx * t * t * t; double y = cury * u * u * u + 3.0 * cpy0 * t * u * u + 3.0 * cpy1 * t * t * u + endy * t * t * t; accum(bounds, x, y); } }