| Line | Hits | Source |
|---|---|---|
| 1 | /* | |
| 2 | * Copyright (c) 2003, the JUNG Project and the Regents of the University of | |
| 3 | * California All rights reserved. | |
| 4 | * | |
| 5 | * This software is open-source under the BSD license; see either "license.txt" | |
| 6 | * or http://jung.sourceforge.net/license.txt for a description. | |
| 7 | * | |
| 8 | * Created on Jul 20, 2004 | |
| 9 | */ | |
| 10 | package edu.uci.ics.jung.visualization; | |
| 11 | ||
| 12 | import java.awt.Shape; | |
| 13 | import java.awt.geom.AffineTransform; | |
| 14 | import java.awt.geom.Ellipse2D; | |
| 15 | import java.awt.geom.GeneralPath; | |
| 16 | import java.awt.geom.Point2D; | |
| 17 | import java.awt.geom.Rectangle2D; | |
| 18 | import java.awt.geom.RoundRectangle2D; | |
| 19 | ||
| 20 | import edu.uci.ics.jung.graph.Vertex; | |
| 21 | import edu.uci.ics.jung.graph.decorators.ConstantVertexAspectRatioFunction; | |
| 22 | import edu.uci.ics.jung.graph.decorators.ConstantVertexSizeFunction; | |
| 23 | import edu.uci.ics.jung.graph.decorators.VertexAspectRatioFunction; | |
| 24 | import edu.uci.ics.jung.graph.decorators.VertexSizeFunction; | |
| 25 | ||
| 26 | /** | |
| 27 | * A utility class for generating <code>Shape</code>s for drawing vertices. | |
| 28 | * The available shapes include rectangles, rounded rectangles, ellipses, | |
| 29 | * regular polygons, and regular stars. The dimensions of the requested | |
| 30 | * shapes are defined by the specified <code>VertexSizeFunction</code> | |
| 31 | * and <code>VertexAspectRatioFunction</code> implementations: the width | |
| 32 | * of the bounding box of the shape is given by the vertex size, and the | |
| 33 | * height is given by the size multiplied by the vertex's aspect ratio. | |
| 34 | * | |
| 35 | * @author Joshua O'Madadhain | |
| 36 | */ | |
| 37 | public class VertexShapeFactory | |
| 38 | { | |
| 39 | protected VertexSizeFunction vsf; | |
| 40 | protected VertexAspectRatioFunction varf; | |
| 41 | ||
| 42 | /** | |
| 43 | * Creates a <code>VertexShapeFactory</code> with the specified | |
| 44 | * vertex size and aspect ratio functions. | |
| 45 | */ | |
| 46 | public VertexShapeFactory(VertexSizeFunction vsf, VertexAspectRatioFunction varf) | |
| 47 | 0 | { |
| 48 | 0 | this.vsf = vsf; |
| 49 | 0 | this.varf = varf; |
| 50 | 0 | } |
| 51 | ||
| 52 | /** | |
| 53 | * Creates a <code>VertexShapeFactory</code> with a constant size of | |
| 54 | * 10 and a constant aspect ratio of 1. | |
| 55 | */ | |
| 56 | public VertexShapeFactory() | |
| 57 | { | |
| 58 | 0 | this(new ConstantVertexSizeFunction(10), |
| 59 | new ConstantVertexAspectRatioFunction(1.0f)); | |
| 60 | 0 | } |
| 61 | ||
| 62 | 0 | private static final Rectangle2D theRectangle = new Rectangle2D.Float(); |
| 63 | /** | |
| 64 | * Returns a <code>Rectangle2D</code> whose width and | |
| 65 | * height are defined by this instance's size and | |
| 66 | * aspect ratio functions for this vertex. | |
| 67 | */ | |
| 68 | public Rectangle2D getRectangle(Vertex v) | |
| 69 | { | |
| 70 | 0 | float width = vsf.getSize(v); |
| 71 | 0 | float height = width * varf.getAspectRatio(v); |
| 72 | 0 | float h_offset = -(width / 2); |
| 73 | 0 | float v_offset = -(height / 2); |
| 74 | 0 | theRectangle.setFrame(h_offset, v_offset, width, height); |
| 75 | 0 | return theRectangle; |
| 76 | } | |
| 77 | ||
| 78 | 0 | private static final Ellipse2D theEllipse = new Ellipse2D.Float(); |
| 79 | /** | |
| 80 | * Returns a <code>Ellipse2D</code> whose width and | |
| 81 | * height are defined by this instance's size and | |
| 82 | * aspect ratio functions for this vertex. | |
| 83 | */ | |
| 84 | public Ellipse2D getEllipse(Vertex v) | |
| 85 | { | |
| 86 | 0 | theEllipse.setFrame(getRectangle(v)); |
| 87 | 0 | return theEllipse; |
| 88 | } | |
| 89 | ||
| 90 | 0 | private static final RoundRectangle2D theRoundRectangle = |
| 91 | new RoundRectangle2D.Float(); | |
| 92 | /** | |
| 93 | * Returns a <code>RoundRectangle2D</code> whose width and | |
| 94 | * height are defined by this instance's size and | |
| 95 | * aspect ratio functions for this vertex. The arc size is | |
| 96 | * set to be half the minimum of the height and width of the frame. | |
| 97 | */ | |
| 98 | public RoundRectangle2D getRoundRectangle(Vertex v) | |
| 99 | { | |
| 100 | 0 | Rectangle2D frame = getRectangle(v); |
| 101 | 0 | float arc_size = (float)Math.min(frame.getHeight(), frame.getWidth()) / 2; |
| 102 | 0 | theRoundRectangle.setRoundRect(frame.getX(), frame.getY(), |
| 103 | frame.getWidth(), frame.getHeight(), arc_size, arc_size); | |
| 104 | 0 | return theRoundRectangle; |
| 105 | } | |
| 106 | ||
| 107 | 0 | private static final GeneralPath thePolygon = new GeneralPath(); |
| 108 | /** | |
| 109 | * Returns a regular <code>num_sides</code>-sided | |
| 110 | * <code>Polygon</code> whose bounding | |
| 111 | * box's width and height are defined by this instance's size and | |
| 112 | * aspect ratio functions for this vertex. | |
| 113 | * @param num_sides the number of sides of the polygon; must be >= 3. | |
| 114 | */ | |
| 115 | public Shape getRegularPolygon(Vertex v, int num_sides) | |
| 116 | { | |
| 117 | 0 | if (num_sides < 3) |
| 118 | 0 | throw new IllegalArgumentException("Number of sides must be >= 3"); |
| 119 | 0 | Rectangle2D frame = getRectangle(v); |
| 120 | 0 | float width = (float)frame.getWidth(); |
| 121 | 0 | float height = (float)frame.getHeight(); |
| 122 | ||
| 123 | // generate coordinates | |
| 124 | 0 | double angle = 0; |
| 125 | 0 | thePolygon.reset(); |
| 126 | 0 | thePolygon.moveTo(0,0); |
| 127 | 0 | thePolygon.lineTo(width, 0); |
| 128 | 0 | double theta = (2 * Math.PI) / num_sides; |
| 129 | 0 | for (int i = 2; i < num_sides; i++) |
| 130 | { | |
| 131 | 0 | angle -= theta; |
| 132 | 0 | float delta_x = (float) (width * Math.cos(angle)); |
| 133 | 0 | float delta_y = (float) (width * Math.sin(angle)); |
| 134 | 0 | Point2D prev = thePolygon.getCurrentPoint(); |
| 135 | 0 | thePolygon.lineTo((float)prev.getX() + delta_x, (float)prev.getY() + delta_y); |
| 136 | } | |
| 137 | 0 | thePolygon.closePath(); |
| 138 | ||
| 139 | // scale polygon to be right size, translate to center at (0,0) | |
| 140 | 0 | Rectangle2D r = thePolygon.getBounds2D(); |
| 141 | 0 | double scale_x = width / r.getWidth(); |
| 142 | 0 | double scale_y = height / r.getHeight(); |
| 143 | ||
| 144 | 0 | AffineTransform at = AffineTransform.getTranslateInstance(-width/2, height/2); |
| 145 | 0 | at.scale(scale_x, scale_y); |
| 146 | ||
| 147 | 0 | Shape shape = at.createTransformedShape(thePolygon); |
| 148 | 0 | return shape; |
| 149 | } | |
| 150 | ||
| 151 | /** | |
| 152 | * Returns a regular <code>Polygon</code> of <code>num_points</code> | |
| 153 | * points whose bounding | |
| 154 | * box's width and height are defined by this instance's size and | |
| 155 | * aspect ratio functions for this vertex. | |
| 156 | * @param num_points the number of points of the polygon; must be >= 5. | |
| 157 | */ | |
| 158 | public Shape getRegularStar(Vertex v, int num_points) | |
| 159 | { | |
| 160 | 0 | if (num_points < 5) |
| 161 | 0 | throw new IllegalArgumentException("Number of sides must be >= 5"); |
| 162 | 0 | Rectangle2D frame = getRectangle(v); |
| 163 | 0 | float width = (float) frame.getWidth(); |
| 164 | 0 | float height = (float) frame.getHeight(); |
| 165 | ||
| 166 | // generate coordinates | |
| 167 | 0 | double theta = (2 * Math.PI) / num_points; |
| 168 | 0 | double angle = -theta/2; |
| 169 | 0 | thePolygon.reset(); |
| 170 | 0 | thePolygon.moveTo(0,0); |
| 171 | 0 | float delta_x = width * (float)Math.cos(angle); |
| 172 | 0 | float delta_y = width * (float)Math.sin(angle); |
| 173 | 0 | Point2D prev = thePolygon.getCurrentPoint(); |
| 174 | 0 | thePolygon.lineTo((float)prev.getX() + delta_x, (float)prev.getY() + delta_y); |
| 175 | 0 | for (int i = 1; i < num_points; i++) |
| 176 | { | |
| 177 | 0 | angle += theta; |
| 178 | 0 | delta_x = width * (float)Math.cos(angle); |
| 179 | 0 | delta_y = width * (float)Math.sin(angle); |
| 180 | 0 | prev = thePolygon.getCurrentPoint(); |
| 181 | 0 | thePolygon.lineTo((float)prev.getX() + delta_x, (float)prev.getY() + delta_y); |
| 182 | 0 | angle -= theta*2; |
| 183 | 0 | delta_x = width * (float)Math.cos(angle); |
| 184 | 0 | delta_y = width * (float)Math.sin(angle); |
| 185 | 0 | prev = thePolygon.getCurrentPoint(); |
| 186 | 0 | thePolygon.lineTo((float)prev.getX() + delta_x, (float)prev.getY() + delta_y); |
| 187 | } | |
| 188 | 0 | thePolygon.closePath(); |
| 189 | ||
| 190 | // scale polygon to be right size, translate to center at (0,0) | |
| 191 | 0 | Rectangle2D r = thePolygon.getBounds2D(); |
| 192 | 0 | double scale_x = width / r.getWidth(); |
| 193 | 0 | double scale_y = height / r.getHeight(); |
| 194 | ||
| 195 | 0 | float translationX = (float) (r.getMinX() + r.getWidth()/2); |
| 196 | 0 | float translationY = (float) (r.getMinY() + r.getHeight()/2); |
| 197 | ||
| 198 | 0 | AffineTransform at = AffineTransform.getScaleInstance(scale_x, scale_y); |
| 199 | 0 | at.translate(-translationX, -translationY); |
| 200 | ||
| 201 | 0 | Shape shape = at.createTransformedShape(thePolygon); |
| 202 | 0 | return shape; |
| 203 | } | |
| 204 | } |
|
this report was generated by version 1.0.5 of jcoverage. |
copyright © 2003, jcoverage ltd. all rights reserved. |