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