001    /*--------------------------------------------------------------------------+
002    $Id: GraphicsUtils.java 26268 2010-02-18 10:44:30Z juergens $
003    |                                                                          |
004    | Copyright 2005-2010 Technische Universitaet Muenchen                     |
005    |                                                                          |
006    | Licensed under the Apache License, Version 2.0 (the "License");          |
007    | you may not use this file except in compliance with the License.         |
008    | You may obtain a copy of the License at                                  |
009    |                                                                          |
010    |    http://www.apache.org/licenses/LICENSE-2.0                            |
011    |                                                                          |
012    | Unless required by applicable law or agreed to in writing, software      |
013    | distributed under the License is distributed on an "AS IS" BASIS,        |
014    | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
015    | See the License for the specific language governing permissions and      |
016    | limitations under the License.                                           |
017    +--------------------------------------------------------------------------*/
018    package edu.tum.cs.commons.image;
019    
020    import java.awt.Point;
021    import java.awt.Rectangle;
022    import java.awt.geom.GeneralPath;
023    
024    /**
025     * Utility classes for graphics.
026     * 
027     * @author hummelb
028     * @author $Author: juergens $
029     * @version $Rev: 26268 $
030     * @levd.rating GREEN Hash: 1143143992222183FB5A5906384AA829
031     */
032    public class GraphicsUtils {
033    
034            /**
035             * Returns a path for the arrow at the end of an edge from p1 to p2.
036             * 
037             * @param arrowBarbSize
038             *            gives the size of the barb in pixels (i.e. the size of the
039             *            arrow tip)
040             * @param arrowPhi
041             *            gives the angle between the barbs and the center line, i.e.
042             *            this is half of the angle of the arrow tip.
043             */
044            public static GeneralPath getArrowHead(Point p1, Point p2,
045                            int arrowBarbSize, double arrowPhi) {
046                    double theta = Math.atan2(p2.y - p1.y, p2.x - p1.x);
047    
048                    GeneralPath path = new GeneralPath();
049    
050                    // Add an arrow head at p2
051                    double x = p2.x + arrowBarbSize * Math.cos(theta + Math.PI - arrowPhi);
052                    double y = p2.y + arrowBarbSize * Math.sin(theta + Math.PI - arrowPhi);
053                    path.moveTo((float) x, (float) y);
054                    path.lineTo(p2.x, p2.y);
055                    x = p2.x + arrowBarbSize * Math.cos(theta + Math.PI + arrowPhi);
056                    y = p2.y + arrowBarbSize * Math.sin(theta + Math.PI + arrowPhi);
057                    path.lineTo((float) x, (float) y);
058    
059                    return path;
060            }
061    
062            /**
063             * The ChopboxAnchor's location is found by calculating the intersection of
064             * a line drawn from the center point of a box to a reference point and that
065             * box. Code borrowed from org.eclipse.draw2d.ChopboxAnchor.
066             */
067            public static Point getChopboxAnchor(Rectangle box, Point referencePoint) {
068    
069                    double baseX = box.getCenterX();
070                    double baseY = box.getCenterY();
071                    double refX = referencePoint.x;
072                    double refY = referencePoint.y;
073    
074                    // This avoids divide-by-zero
075                    if (box.isEmpty() || (refX == baseX && refY == baseY)) {
076                            return new Point((int) refX, (int) refY);
077                    }
078    
079                    double dx = refX - baseX;
080                    double dy = refY - baseY;
081    
082                    // r.width, r.height, dx, and dy are guaranteed to be non-zero.
083                    double scale = 0.5 / Math.max(Math.abs(dx) / box.width, Math.abs(dy)
084                                    / box.height);
085                    baseX += dx * scale;
086                    baseY += dy * scale;
087                    return new Point((int) Math.round(baseX), (int) Math.round(baseY));
088            }
089    }